// Copyright (C) 2008 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.FancyFlexTable;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.GerritConfig;
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.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.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
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.Panel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwtexpui.globalkey.client.NpTextBox;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtjsonrpc.client.VoidResult;

import java.util.HashSet;
import java.util.List;
import java.util.Map;

public class ProjectRightsPanel extends Composite {
  private Project.NameKey projectName;

  private RightsTable rights;
  private Button delRight;
  private Button addRight;
  private ListBox catBox;
  private ListBox rangeMinBox;
  private ListBox rangeMaxBox;
  private NpTextBox nameTxtBox;
  private SuggestBox nameTxt;
  private NpTextBox referenceTxt;

  public ProjectRightsPanel(final Project.NameKey toShow) {
    projectName = toShow;

    final FlowPanel body = new FlowPanel();
    initRights(body);
    initWidget(body);
  }

  @Override
  protected void onLoad() {
    enableForm(false);
    super.onLoad();

    Util.PROJECT_SVC.projectDetail(projectName,
        new GerritCallback<ProjectDetail>() {
          public void onSuccess(final ProjectDetail result) {
            enableForm(true);
            display(result);
          }
        });
  }

  private void enableForm(final boolean on) {
    delRight.setEnabled(on);

    final boolean canAdd = on && catBox.getItemCount() > 0;
    addRight.setEnabled(canAdd);
    nameTxtBox.setEnabled(canAdd);
    referenceTxt.setEnabled(canAdd);
    catBox.setEnabled(canAdd);
    rangeMinBox.setEnabled(canAdd);
    rangeMaxBox.setEnabled(canAdd);
  }

  private void initRights(final Panel body) {
    final FlowPanel addPanel = new FlowPanel();
    addPanel.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());

    final Grid addGrid = new Grid(5, 2);

    catBox = new ListBox();
    rangeMinBox = new ListBox();
    rangeMaxBox = new ListBox();

    catBox.addChangeHandler(new ChangeHandler() {
      @Override
      public void onChange(final ChangeEvent event) {
        updateCategorySelection();
      }
    });
    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(projectName)
          && 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());
    }

    addGrid.setText(0, 0, Util.C.columnApprovalCategory() + ":");
    addGrid.setWidget(0, 1, catBox);

    nameTxtBox = new NpTextBox();
    nameTxt = new SuggestBox(new AccountGroupSuggestOracle(), nameTxtBox);
    nameTxtBox.setVisibleLength(50);
    nameTxtBox.setText(Util.C.defaultAccountGroupName());
    nameTxtBox.addStyleName(Gerrit.RESOURCES.css().inputFieldTypeHint());
    nameTxtBox.addFocusHandler(new FocusHandler() {
      @Override
      public void onFocus(FocusEvent event) {
        if (Util.C.defaultAccountGroupName().equals(nameTxtBox.getText())) {
          nameTxtBox.setText("");
          nameTxtBox.removeStyleName(Gerrit.RESOURCES.css()
              .inputFieldTypeHint());
        }
      }
    });
    nameTxtBox.addBlurHandler(new BlurHandler() {
      @Override
      public void onBlur(BlurEvent event) {
        if ("".equals(nameTxtBox.getText())) {
          nameTxtBox.setText(Util.C.defaultAccountGroupName());
          nameTxtBox.addStyleName(Gerrit.RESOURCES.css().inputFieldTypeHint());
        }
      }
    });
    nameTxtBox.addKeyPressHandler(new KeyPressHandler() {
      @Override
      public void onKeyPress(KeyPressEvent event) {
        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
          doAddNewRight();
        }
      }
    });
    addGrid.setText(1, 0, Util.C.columnGroupName() + ":");
    addGrid.setWidget(1, 1, nameTxt);

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

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

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

    addGrid.setText(4, 0, "");
    addGrid.setWidget(4, 1, rangeMaxBox);

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

    rights = new RightsTable();

    delRight = new Button(Util.C.buttonDeleteGroupMembers());
    delRight.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        rights.deleteChecked();
      }
    });

    body.add(new SmallHeading(Util.C.headingAccessRights()));
    body.add(rights);
    body.add(delRight);
    body.add(addPanel);

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

  void display(final ProjectDetail result) {
    rights.display(result.groups, result.rights);
  }

  private void doAddNewRight() {
    int idx = catBox.getSelectedIndex();
    final ApprovalType at;
    ApprovalCategoryValue min, max;
    if (idx < 0) {
      return;
    }
    at =
        Gerrit.getConfig().getApprovalTypes().getApprovalType(
            new ApprovalCategory.Id(catBox.getValue(idx)));
    if (at == null) {
      return;
    }

    idx = rangeMinBox.getSelectedIndex();
    if (idx < 0) {
      return;
    }
    min = at.getValue(Short.parseShort(rangeMinBox.getValue(idx)));
    if (min == null) {
      return;
    }

    idx = rangeMaxBox.getSelectedIndex();
    if (idx < 0) {
      return;
    }
    max = at.getValue(Short.parseShort(rangeMaxBox.getValue(idx)));
    if (max == null) {
      return;
    }

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

    final String refPattern = referenceTxt.getText();

    if (min.getValue() > max.getValue()) {
      // If the user selects it backwards in the web UI, help them out
      // by reversing the order to what we would expect.
      //
      final ApprovalCategoryValue newMin = max;
      final ApprovalCategoryValue newMax = min;
      min = newMin;
      max = newMax;
    }

    addRight.setEnabled(false);
    Util.PROJECT_SVC.addRight(projectName, at.getCategory().getId(), groupName,
        refPattern, min.getValue(), max.getValue(),
        new GerritCallback<ProjectDetail>() {
          public void onSuccess(final ProjectDetail result) {
            addRight.setEnabled(true);
            nameTxt.setText("");
            referenceTxt.setText("");
            display(result);
          }

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

  private void updateCategorySelection() {
    final int idx = catBox.getSelectedIndex();
    final ApprovalType at;
    if (idx >= 0) {
      at =
          Gerrit.getConfig().getApprovalTypes().getApprovalType(
              new ApprovalCategory.Id(catBox.getValue(idx)));
    } else {
      at = null;
    }

    if (at == null || at.getValues().isEmpty()) {
      rangeMinBox.setEnabled(false);
      rangeMaxBox.setEnabled(false);
      referenceTxt.setEnabled(false);
      addRight.setEnabled(false);
      return;
    }

    // TODO Support per-branch READ access.
    if (ApprovalCategory.READ.equals(at.getCategory().getId())) {
      referenceTxt.setText("");
      referenceTxt.setEnabled(false);
    } else {
      referenceTxt.setEnabled(true);
    }

    int curIndex = 0, minIndex = -1, maxIndex = -1;
    rangeMinBox.clear();
    rangeMaxBox.clear();
    for (final ApprovalCategoryValue v : at.getValues()) {
      final String vStr = String.valueOf(v.getValue());
      String nStr = vStr + ": " + v.getName();
      if (v.getValue() > 0) {
        nStr = "+" + nStr;
      }

      rangeMinBox.addItem(nStr, vStr);
      rangeMaxBox.addItem(nStr, vStr);

      if (v.getValue() < 0) {
        minIndex = curIndex;
      }
      if (maxIndex < 0 && v.getValue() > 0) {
        maxIndex = curIndex;
      }

      curIndex++;
    }
    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.
      minIndex = maxIndex;
    }
    rangeMinBox.setSelectedIndex(minIndex >= 0 ? minIndex : 0);
    rangeMaxBox.setSelectedIndex(maxIndex >= 0 ? maxIndex : curIndex - 1);

    addRight.setEnabled(true);
  }

  private class RightsTable extends FancyFlexTable<RefRight> {
    RightsTable() {
      table.setWidth("");
      table.setText(0, 2, Util.C.columnApprovalCategory());
      table.setText(0, 3, Util.C.columnGroupName());
      table.setText(0, 4, Util.C.columnRefName());
      table.setText(0, 5, Util.C.columnRightRange());

      final FlexCellFormatter fmt = table.getFlexCellFormatter();
      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
      fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
      fmt.addStyleName(0, 5, Gerrit.RESOURCES.css().dataHeader());
    }

    void deleteChecked() {
      final HashSet<RefRight.Key> refRightIds = new HashSet<RefRight.Key>();
      for (int row = 1; row < table.getRowCount(); row++) {
        RefRight r = getRowItem(row);
        if (r != null && table.getWidget(row, 1) instanceof CheckBox
            && ((CheckBox) table.getWidget(row, 1)).getValue()) {
          refRightIds.add(r.getKey());
        }
      }

      GerritCallback<VoidResult> updateTable =
          new GerritCallback<VoidResult>() {
            @Override
            public void onSuccess(final VoidResult result) {
              for (int row = 1; row < table.getRowCount();) {
                RefRight r = getRowItem(row);
                if (r != null && refRightIds.contains(r.getKey())) {
                  table.removeRow(row);
                } else {
                  row++;
                }
              }
            }
          };
      if (!refRightIds.isEmpty()) {
        Util.PROJECT_SVC.deleteRight(projectName, refRightIds, updateTable);
      }
    }

    void display(final Map<AccountGroup.Id, AccountGroup> groups,
        final List<RefRight> refRights) {
      while (1 < table.getRowCount())
        table.removeRow(table.getRowCount() - 1);

      for (final RefRight r : refRights) {
        final int row = table.getRowCount();
        table.insertRow(row);
        applyDataRowStyle(row);
        populate(row, groups, r);
      }
    }

    void populate(final int row,
        final Map<AccountGroup.Id, AccountGroup> groups, final RefRight r) {
      final GerritConfig config = Gerrit.getConfig();
      final ApprovalType ar =
          config.getApprovalTypes().getApprovalType(r.getApprovalCategoryId());
      final AccountGroup group = groups.get(r.getAccountGroupId());

      if (!projectName.equals(Gerrit.getConfig().getWildProject())
          && Gerrit.getConfig().getWildProject().equals(r.getProjectNameKey())) {
        table.setText(row, 1, "");
      } else {
        table.setWidget(row, 1, new CheckBox());
      }

      if (ar != null) {
        table.setText(row, 2, ar.getCategory().getName());
      } else {
        table.setText(row, 2, r.getApprovalCategoryId().get());
      }

      if (group != null) {
        table.setText(row, 3, group.getName());
      } else {
        table.setText(row, 3, Util.M.deletedGroup(r.getAccountGroupId().get()));
      }

      table.setText(row, 4, r.getRefPattern());

      {
        final SafeHtmlBuilder m = new SafeHtmlBuilder();
        final ApprovalCategoryValue min, max;
        min = ar != null ? ar.getValue(r.getMinValue()) : null;
        max = ar != null ? ar.getValue(r.getMaxValue()) : null;

        formatValue(m, r.getMinValue(), min);
        if (r.getMinValue() != r.getMaxValue()) {
          m.br();
          formatValue(m, r.getMaxValue(), max);
        }
        SafeHtml.set(table, row, 5, m);
      }

      final FlexCellFormatter fmt = table.getFlexCellFormatter();
      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());
      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
      fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
      fmt.addStyleName(row, 5, Gerrit.RESOURCES.css().dataCell());
      fmt.addStyleName(row, 5, Gerrit.RESOURCES.css()
          .projectAdminApprovalCategoryRangeLine());

      setRowItem(row, r);
    }

    private void formatValue(final SafeHtmlBuilder m, final short v,
        final ApprovalCategoryValue e) {
      m.openSpan();
      m
          .setStyleName(Gerrit.RESOURCES.css()
              .projectAdminApprovalCategoryValue());
      if (v == 0) {
        m.append(' ');
      } else if (v > 0) {
        m.append('+');
      }
      m.append(v);
      m.closeSpan();
      if (e != null) {
        m.append(": ");
        m.append(e.getName());
      }
    }
  }
}
