// 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.AccountGroup;
import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.RefRight;
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.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
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)
          && !c.getId().canBeOnWildProject()) {
        // 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;
  }
}
