// Copyright (C) 2010 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.client.admin;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.AccountGroupSuggestOracle;
import com.google.gerrit.client.ui.HintTextBox;
import com.google.gerrit.client.ui.RPCSuggestOracle;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ProjectDetail;
import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.RefRight;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.SuggestBox;

public class AccessRightEditor extends Composite
    implements HasValueChangeHandlers<ProjectDetail> {
  private Project.NameKey projectKey;
  private ListBox catBox;
  private HintTextBox nameTxt;
  private SuggestBox nameSug;
  private HintTextBox referenceTxt;
  private ListBox topBox;
  private ListBox botBox;
  private Button addBut;
  private Button clearBut;

  public AccessRightEditor(final Project.NameKey key) {
    projectKey = key;

    initWidgets();
    initCategories();

    final Grid grid = new Grid(5, 2);
    grid.setText(0, 0, Util.C.columnApprovalCategory() + ":");
    grid.setWidget(0, 1, catBox);

    grid.setText(1, 0, Util.C.columnGroupName() + ":");
    grid.setWidget(1, 1, nameSug);

    grid.setText(2, 0, Util.C.columnRefName() + ":");
    grid.setWidget(2, 1, referenceTxt);

    grid.setText(3, 0, Util.C.columnRightRange() + ":");
    grid.setWidget(3, 1, topBox);

    grid.setText(4, 0, "");
    grid.setWidget(4, 1, botBox);

    FlowPanel fp = new FlowPanel();
    fp.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());

    fp.add(grid);
    fp.add(addBut);
    fp.add(clearBut);
    initWidget(fp);
  }

  protected void initWidgets() {
    catBox = new ListBox();
    catBox.addChangeHandler(new ChangeHandler() {
      @Override
      public void onChange(final ChangeEvent event) {
        updateCategorySelection();
      }
    });

    nameTxt = new HintTextBox();
    nameSug = new SuggestBox(new RPCSuggestOracle(
        new AccountGroupSuggestOracle()), nameTxt);
    nameTxt.setVisibleLength(50);
    nameTxt.setHintText(Util.C.defaultAccountGroupName());

    referenceTxt = new HintTextBox();
    referenceTxt.setVisibleLength(50);
    referenceTxt.setText("");
    referenceTxt.addKeyPressHandler(new KeyPressHandler() {
      @Override
      public void onKeyPress(KeyPressEvent event) {
        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
          doAddNewRight();
        }
      }
    });

    topBox = new ListBox();
    botBox = new ListBox();

    addBut = new Button(Util.C.buttonAddProjectRight());
    addBut.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        doAddNewRight();
      }
    });

    clearBut = new Button(Util.C.buttonClearProjectRight());
    clearBut.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        clear();
      }
    });
  }

  protected void initCategories() {
    for (final ApprovalType at : Gerrit.getConfig().getApprovalTypes()
        .getApprovalTypes()) {
      final ApprovalCategory c = at.getCategory();
      catBox.addItem(c.getName(), c.getId().get());
    }
    for (final ApprovalType at : Gerrit.getConfig().getApprovalTypes()
        .getActionTypes()) {
      final ApprovalCategory c = at.getCategory();
      if (Gerrit.getConfig().getWildProject().equals(projectKey)
          && ApprovalCategory.OWN.equals(c.getId())) {
        // Giving out control of the WILD_PROJECT to other groups beyond
        // Administrators is dangerous. Having control over WILD_PROJECT
        // is about the same as having Administrator access as users are
        // able to affect grants in all projects on the system.
        //
        continue;
      }
      catBox.addItem(c.getName(), c.getId().get());
    }

    if (catBox.getItemCount() > 0) {
      catBox.setSelectedIndex(0);
      updateCategorySelection();
    }
  }

  public void enableForm(final boolean on) {
    final boolean canAdd = on && catBox.getItemCount() > 0;
    addBut.setEnabled(canAdd);
    clearBut.setEnabled(canAdd);
    nameTxt.setEnabled(canAdd);
    referenceTxt.setEnabled(canAdd);
    catBox.setEnabled(canAdd);
    topBox.setEnabled(canAdd);
    botBox.setEnabled(canAdd);
  }

  public void clear() {
    setCat(null);
    setName("");
    setReference("");
  }

  public void load(final RefRight right, final AccountGroup group) {
    final ApprovalType atype =
       Gerrit.getConfig().getApprovalTypes().getApprovalType(
          right.getApprovalCategoryId());

    setCat(atype != null ? atype.getCategory().getName()
                         : right.getApprovalCategoryId().get() );

    setName(group.getName());
    setReference(right.getRefPatternForDisplay());

    setRange(atype.getCategory().isRange() ? atype.getValue(right.getMinValue())
             : null, atype.getValue(right.getMaxValue()) );
  }

  protected void doAddNewRight() {
    final ApprovalType at = getApprovalType();
    ApprovalCategoryValue min = getMin(at);
    ApprovalCategoryValue max = getMax(at);

    if (at == null || min == null || max == null) {
      return;
    }

    final String groupName = nameSug.getText();
    if ("".equals(groupName)
        || Util.C.defaultAccountGroupName().equals(groupName)) {
      return;
    }

    final String refPattern = referenceTxt.getText();

    addBut.setEnabled(false);
    Util.PROJECT_SVC.addRight(projectKey, at.getCategory().getId(),
        groupName, refPattern, min.getValue(), max.getValue(),
        new GerritCallback<ProjectDetail>() {
          public void onSuccess(final ProjectDetail result) {
            addBut.setEnabled(true);
            nameSug.setText("");
            referenceTxt.setText("");
            ValueChangeEvent.fire(AccessRightEditor.this, result);
          }

          @Override
          public void onFailure(final Throwable caught) {
            addBut.setEnabled(true);
            super.onFailure(caught);
          }
        });
  }

  protected void updateCategorySelection() {
    final ApprovalType at = getApprovalType();

    if (at == null || at.getValues().isEmpty()) {
      topBox.setEnabled(false);
      botBox.setEnabled(false);
      referenceTxt.setEnabled(false);
      addBut.setEnabled(false);
      clearBut.setEnabled(false);
      return;
    }

    updateRanges(at);
  }

  protected void updateRanges(final ApprovalType at) {
    ApprovalCategoryValue min = null, max = null, last = null;

    topBox.clear();
    botBox.clear();

    for(final ApprovalCategoryValue v : at.getValues()) {
      final int nval = v.getValue();
      final String vStr = String.valueOf(nval);

      String nStr = vStr + ": " + v.getName();
      if (nval > 0) {
        nStr = "+" + nStr;
      }

      topBox.addItem(nStr, vStr);
      botBox.addItem(nStr, vStr);

      if (min == null || nval < 0) {
        min = v;
      } else if (max == null && nval > 0) {
        max = v;
      }
      last = v;
    }

    if (max == null) {
      max = last;
    }

    if (ApprovalCategory.READ.equals(at.getCategory().getId())) {
      // Special case; for READ the most logical range is just
      // +1 READ, so assume that as the default for both.
      min = max;
    }

    if (! at.getCategory().isRange()) {
      max = null;
    }

    setRange(min, max);
  }

  protected void setCat(final String cat) {
    if (cat == null) {
      catBox.setSelectedIndex(0);
    } else {
      setSelectedText(catBox, cat);
    }
    updateCategorySelection();
  }

  protected void setName(final String name) {
    nameTxt.setText(name);
  }

  protected void setReference(final String ref) {
    referenceTxt.setText(ref);
  }

  protected void setRange(final ApprovalCategoryValue min,
                          final ApprovalCategoryValue max) {
    if (min == null || max == null) {
      botBox.setVisible(false);
      if (max != null) {
        setSelectedValue(topBox, "" + max.getValue());
        return;
      }
    } else {
      botBox.setVisible(true);
      setSelectedValue(botBox, "" + max.getValue());
    }
    setSelectedValue(topBox, "" + min.getValue());
  }

  private ApprovalType getApprovalType() {
    int idx = catBox.getSelectedIndex();
    if (idx < 0) {
      return null;
    }
    return Gerrit.getConfig().getApprovalTypes().getApprovalType(
             new ApprovalCategory.Id(catBox.getValue(idx)));
  }

  public ApprovalCategoryValue getMin(ApprovalType at) {
    final ApprovalCategoryValue top = getTop(at);
    final ApprovalCategoryValue bot = getBot(at);
    if (bot == null) {
      for (final ApprovalCategoryValue v : at.getValues()) {
        if (0 <= v.getValue() && v.getValue() <= top.getValue()) {
          return v;
        }
      }
      return at.getMin();
    }

    if (top.getValue() > bot.getValue()) {
      return bot;
    }
    return top;
  }

  public ApprovalCategoryValue getMax(ApprovalType at) {
    final ApprovalCategoryValue top = getTop(at);
    final ApprovalCategoryValue bot = getBot(at);
    if (bot == null || bot.getValue() < top.getValue()) {
      return top;
    }
    return bot;
  }

  protected ApprovalCategoryValue getTop(ApprovalType at) {
    int idx = topBox.getSelectedIndex();
    if (idx < 0) {
      return null;
    }
    return at.getValue(Short.parseShort(topBox.getValue(idx)));
  }

  protected ApprovalCategoryValue getBot(ApprovalType at) {
    int idx = botBox.getSelectedIndex();
    if (idx < 0 || ! botBox.isVisible()) {
      return null;
    }
    return at.getValue(Short.parseShort(botBox.getValue(idx)));
  }

  public HandlerRegistration addValueChangeHandler(
      final ValueChangeHandler<ProjectDetail> handler) {
    return addHandler(handler, ValueChangeEvent.getType());
  }

  public static boolean setSelectedText(ListBox box, String text) {
    if (text == null) {
      return false;
    }
    for (int i =0 ; i < box.getItemCount(); i++) {
      if (text.equals(box.getItemText(i))) {
        box.setSelectedIndex(i);
        return true;
      }
    }
    return false;
  }

  public static boolean setSelectedValue(ListBox box, String value) {
    if (value == null) {
      return false;
    }
    for (int i =0 ; i < box.getItemCount(); i++) {
      if (value.equals(box.getValue(i))) {
        box.setSelectedIndex(i);
        return true;
      }
    }
    return false;
  }
}
