// 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.GerritUiExtensionPoint;
import com.google.gerrit.client.StringListPanel;
import com.google.gerrit.client.access.AccessMap;
import com.google.gerrit.client.access.ProjectAccessInfo;
import com.google.gerrit.client.actions.ActionButton;
import com.google.gerrit.client.api.ExtensionPanel;
import com.google.gerrit.client.change.Resources;
import com.google.gerrit.client.download.DownloadPanel;
import com.google.gerrit.client.info.ActionInfo;
import com.google.gerrit.client.info.DownloadInfo.DownloadCommandInfo;
import com.google.gerrit.client.info.DownloadInfo.DownloadSchemeInfo;
import com.google.gerrit.client.projects.ConfigInfo;
import com.google.gerrit.client.projects.ConfigInfo.ConfigParameterInfo;
import com.google.gerrit.client.projects.ConfigInfo.ConfigParameterValue;
import com.google.gerrit.client.projects.ConfigInfo.InheritedBooleanInfo;
import com.google.gerrit.client.projects.ProjectApi;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.NpIntTextBox;
import com.google.gerrit.client.ui.OnEditEnabler;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.ProjectState;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.reviewdb.client.Project;
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.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.globalkey.client.NpTextArea;
import com.google.gwtexpui.globalkey.client.NpTextBox;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class ProjectInfoScreen extends ProjectScreen {
  private boolean isOwner;
  private boolean configVisible;

  private LabeledWidgetsGrid grid;
  private Panel pluginOptionsPanel;
  private LabeledWidgetsGrid actionsGrid;

  // Section: Project Options
  private ListBox requireChangeID;
  private ListBox submitType;
  private ListBox state;
  private ListBox contentMerge;
  private ListBox newChangeForAllNotInTarget;
  private ListBox enableSignedPush;
  private ListBox requireSignedPush;
  private ListBox rejectImplicitMerges;
  private ListBox privateByDefault;
  private ListBox workInProgressByDefault;
  private ListBox enableReviewerByEmail;
  private ListBox matchAuthorToCommitterDate;
  private NpTextBox maxObjectSizeLimit;
  private Label effectiveMaxObjectSizeLimit;
  private Map<String, Map<String, HasEnabled>> pluginConfigWidgets;

  // Section: Contributor Agreements
  private ListBox contributorAgreements;
  private ListBox signedOffBy;

  private NpTextArea descTxt;
  private Button saveProject;

  private OnEditEnabler saveEnabler;

  public ProjectInfoScreen(Project.NameKey toShow) {
    super(toShow);
  }

  @Override
  protected void onInitUI() {
    super.onInitUI();

    Resources.I.style().ensureInjected();
    saveProject = new Button(AdminConstants.I.buttonSaveChanges());
    saveProject.setStyleName("");
    saveProject.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            doSave();
          }
        });

    ExtensionPanel extensionPanelTop =
        new ExtensionPanel(GerritUiExtensionPoint.PROJECT_INFO_SCREEN_TOP);
    extensionPanelTop.put(GerritUiExtensionPoint.Key.PROJECT_NAME, getProjectKey().get());
    add(extensionPanelTop);

    add(new ProjectDownloadPanel(getProjectKey().get(), true));

    initDescription();
    grid = new LabeledWidgetsGrid();
    pluginOptionsPanel = new FlowPanel();
    actionsGrid = new LabeledWidgetsGrid();
    initProjectOptions();
    initAgreements();
    add(grid);
    add(pluginOptionsPanel);
    add(saveProject);
    add(actionsGrid);

    ExtensionPanel extensionPanelBottom =
        new ExtensionPanel(GerritUiExtensionPoint.PROJECT_INFO_SCREEN_BOTTOM);
    extensionPanelBottom.put(GerritUiExtensionPoint.Key.PROJECT_NAME, getProjectKey().get());
    add(extensionPanelBottom);
  }

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

    Project.NameKey project = getProjectKey();
    CallbackGroup cbg = new CallbackGroup();
    AccessMap.get(
        project,
        cbg.add(
            new GerritCallback<ProjectAccessInfo>() {
              @Override
              public void onSuccess(ProjectAccessInfo result) {
                isOwner = result.isOwner();
                configVisible = result.configVisible();
                enableForm();
                saveProject.setVisible(isOwner);
              }
            }));
    ProjectApi.getConfig(
        project,
        cbg.addFinal(
            new ScreenLoadCallback<ConfigInfo>(this) {
              @Override
              public void preDisplay(ConfigInfo result) {
                display(result);
              }
            }));

    savedPanel = INFO;
  }

  private void enableForm() {
    enableForm(isOwner);
  }

  private void enableForm(boolean isOwner) {
    state.setEnabled(isOwner);
    submitType.setEnabled(isOwner);
    setEnabledForUseContentMerge();
    newChangeForAllNotInTarget.setEnabled(isOwner);
    if (enableSignedPush != null) {
      enableSignedPush.setEnabled(isOwner);
    }
    if (requireSignedPush != null) {
      requireSignedPush.setEnabled(isOwner);
    }
    descTxt.setEnabled(isOwner);
    contributorAgreements.setEnabled(isOwner);
    signedOffBy.setEnabled(isOwner);
    requireChangeID.setEnabled(isOwner);
    rejectImplicitMerges.setEnabled(isOwner);
    privateByDefault.setEnabled(isOwner);
    workInProgressByDefault.setEnabled(isOwner);
    maxObjectSizeLimit.setEnabled(isOwner);
    enableReviewerByEmail.setEnabled(isOwner);
    matchAuthorToCommitterDate.setEnabled(isOwner);

    if (pluginConfigWidgets != null) {
      for (Map<String, HasEnabled> widgetMap : pluginConfigWidgets.values()) {
        for (HasEnabled widget : widgetMap.values()) {
          widget.setEnabled(isOwner);
        }
      }
    }
  }

  private void initDescription() {
    final VerticalPanel vp = new VerticalPanel();
    vp.add(new SmallHeading(AdminConstants.I.headingDescription()));

    descTxt = new NpTextArea();
    descTxt.setVisibleLines(6);
    descTxt.setCharacterWidth(60);
    vp.add(descTxt);

    add(vp);
    saveEnabler = new OnEditEnabler(saveProject);
    saveEnabler.listenTo(descTxt);
  }

  private void initProjectOptions() {
    grid.addHeader(new SmallHeading(AdminConstants.I.headingProjectOptions()));

    state = new ListBox();
    for (ProjectState stateValue : ProjectState.values()) {
      state.addItem(Util.toLongString(stateValue), stateValue.name());
    }
    saveEnabler.listenTo(state);
    grid.add(AdminConstants.I.headingProjectState(), state);

    submitType = new ListBox();
    for (SubmitType type : SubmitType.values()) {
      submitType.addItem(Util.toLongString(type), type.name());
    }
    submitType.addChangeHandler(
        new ChangeHandler() {
          @Override
          public void onChange(ChangeEvent event) {
            setEnabledForUseContentMerge();
          }
        });
    saveEnabler.listenTo(submitType);
    grid.add(AdminConstants.I.headingProjectSubmitType(), submitType);

    contentMerge = newInheritedBooleanBox();
    saveEnabler.listenTo(contentMerge);
    grid.add(AdminConstants.I.useContentMerge(), contentMerge);

    newChangeForAllNotInTarget = newInheritedBooleanBox();
    saveEnabler.listenTo(newChangeForAllNotInTarget);
    grid.add(AdminConstants.I.createNewChangeForAllNotInTarget(), newChangeForAllNotInTarget);

    requireChangeID = newInheritedBooleanBox();
    saveEnabler.listenTo(requireChangeID);
    grid.addHtml(AdminConstants.I.requireChangeID(), requireChangeID);

    if (Gerrit.info().receive().enableSignedPush()) {
      enableSignedPush = newInheritedBooleanBox();
      saveEnabler.listenTo(enableSignedPush);
      grid.add(AdminConstants.I.enableSignedPush(), enableSignedPush);
      requireSignedPush = newInheritedBooleanBox();
      saveEnabler.listenTo(requireSignedPush);
      grid.add(AdminConstants.I.requireSignedPush(), requireSignedPush);
    }

    rejectImplicitMerges = newInheritedBooleanBox();
    saveEnabler.listenTo(rejectImplicitMerges);
    grid.addHtml(AdminConstants.I.rejectImplicitMerges(), rejectImplicitMerges);

    privateByDefault = newInheritedBooleanBox();
    saveEnabler.listenTo(privateByDefault);
    grid.addHtml(AdminConstants.I.privateByDefault(), privateByDefault);

    workInProgressByDefault = newInheritedBooleanBox();
    saveEnabler.listenTo(workInProgressByDefault);
    grid.addHtml(AdminConstants.I.workInProgressByDefault(), workInProgressByDefault);

    enableReviewerByEmail = newInheritedBooleanBox();
    saveEnabler.listenTo(enableReviewerByEmail);
    grid.addHtml(AdminConstants.I.enableReviewerByEmail(), enableReviewerByEmail);

    matchAuthorToCommitterDate = newInheritedBooleanBox();
    saveEnabler.listenTo(matchAuthorToCommitterDate);
    grid.addHtml(AdminConstants.I.matchAuthorToCommitterDate(), matchAuthorToCommitterDate);

    maxObjectSizeLimit = new NpTextBox();
    saveEnabler.listenTo(maxObjectSizeLimit);
    effectiveMaxObjectSizeLimit = new Label();
    effectiveMaxObjectSizeLimit.setStyleName(
        Gerrit.RESOURCES.css().maxObjectSizeLimitEffectiveLabel());
    HorizontalPanel p = new HorizontalPanel();
    p.add(maxObjectSizeLimit);
    p.add(effectiveMaxObjectSizeLimit);
    grid.addHtml(AdminConstants.I.headingMaxObjectSizeLimit(), p);
  }

  private static ListBox newInheritedBooleanBox() {
    ListBox box = new ListBox();
    for (InheritableBoolean b : InheritableBoolean.values()) {
      box.addItem(b.name(), b.name());
    }
    return box;
  }

  /**
   * Enables the {@link #contentMerge} checkbox if the selected submit type allows the usage of
   * content merge. If the submit type (currently only 'Fast Forward Only') does not allow content
   * merge the useContentMerge checkbox gets disabled.
   */
  private void setEnabledForUseContentMerge() {
    if (SubmitType.FAST_FORWARD_ONLY.equals(
        SubmitType.valueOf(submitType.getValue(submitType.getSelectedIndex())))) {
      contentMerge.setEnabled(false);
      InheritedBooleanInfo b = InheritedBooleanInfo.create();
      b.setConfiguredValue(InheritableBoolean.FALSE);
      setBool(contentMerge, b);
    } else {
      contentMerge.setEnabled(submitType.isEnabled());
    }
  }

  private void initAgreements() {
    grid.addHeader(new SmallHeading(AdminConstants.I.headingAgreements()));

    contributorAgreements = newInheritedBooleanBox();
    if (Gerrit.info().auth().useContributorAgreements()) {
      saveEnabler.listenTo(contributorAgreements);
      grid.add(AdminConstants.I.useContributorAgreements(), contributorAgreements);
    }

    signedOffBy = newInheritedBooleanBox();
    saveEnabler.listenTo(signedOffBy);
    grid.addHtml(AdminConstants.I.useSignedOffBy(), signedOffBy);
  }

  private void setSubmitType(SubmitType newSubmitType) {
    int index = -1;
    if (submitType != null) {
      for (int i = 0; i < submitType.getItemCount(); i++) {
        if (newSubmitType.name().equals(submitType.getValue(i))) {
          index = i;
          break;
        }
      }
      submitType.setSelectedIndex(index);
      setEnabledForUseContentMerge();
    }
  }

  private void setState(ProjectState newState) {
    if (state != null) {
      for (int i = 0; i < state.getItemCount(); i++) {
        if (newState.name().equals(state.getValue(i))) {
          state.setSelectedIndex(i);
          break;
        }
      }
    }
  }

  private void setBool(ListBox box, InheritedBooleanInfo inheritedBoolean) {
    if (box == null) {
      return;
    }
    int inheritedIndex = -1;
    for (int i = 0; i < box.getItemCount(); i++) {
      if (box.getValue(i).startsWith(InheritableBoolean.INHERIT.name())) {
        inheritedIndex = i;
      }
      if (box.getValue(i).startsWith(inheritedBoolean.configuredValue().name())) {
        box.setSelectedIndex(i);
      }
    }
    if (inheritedIndex >= 0) {
      if (Gerrit.info().gerrit().isAllProjects(getProjectKey())) {
        if (box.getSelectedIndex() == inheritedIndex) {
          for (int i = 0; i < box.getItemCount(); i++) {
            if (box.getValue(i).equals(InheritableBoolean.FALSE.name())) {
              box.setSelectedIndex(i);
              break;
            }
          }
        }
        box.removeItem(inheritedIndex);
      } else {
        box.setItemText(
            inheritedIndex,
            InheritableBoolean.INHERIT.name() + " (" + inheritedBoolean.inheritedValue() + ")");
      }
    }
  }

  private static InheritableBoolean getBool(ListBox box) {
    int i = box.getSelectedIndex();
    if (i >= 0) {
      final String selectedValue = box.getValue(i);
      if (selectedValue.startsWith(InheritableBoolean.INHERIT.name())) {
        return InheritableBoolean.INHERIT;
      }
      return InheritableBoolean.valueOf(selectedValue);
    }
    return InheritableBoolean.INHERIT;
  }

  void display(ConfigInfo result) {
    descTxt.setText(result.description());
    setBool(contributorAgreements, result.useContributorAgreements());
    setBool(signedOffBy, result.useSignedOffBy());
    setBool(contentMerge, result.useContentMerge());
    setBool(newChangeForAllNotInTarget, result.createNewChangeForAllNotInTarget());
    setBool(requireChangeID, result.requireChangeId());
    if (Gerrit.info().receive().enableSignedPush()) {
      setBool(enableSignedPush, result.enableSignedPush());
      setBool(requireSignedPush, result.requireSignedPush());
    }
    setBool(rejectImplicitMerges, result.rejectImplicitMerges());
    setBool(privateByDefault, result.privateByDefault());
    setBool(workInProgressByDefault, result.workInProgressByDefault());
    setBool(enableReviewerByEmail, result.enableReviewerByEmail());
    setBool(matchAuthorToCommitterDate, result.matchAuthorToCommitterDate());
    setSubmitType(result.submitType());
    setState(result.state());
    maxObjectSizeLimit.setText(result.maxObjectSizeLimit().configuredValue());
    if (result.maxObjectSizeLimit().inheritedValue() != null) {
      effectiveMaxObjectSizeLimit.setVisible(true);
      effectiveMaxObjectSizeLimit.setText(
          AdminMessages.I.effectiveMaxObjectSizeLimit(result.maxObjectSizeLimit().value()));
      effectiveMaxObjectSizeLimit.setTitle(
          AdminMessages.I.globalMaxObjectSizeLimit(result.maxObjectSizeLimit().inheritedValue()));
    } else {
      effectiveMaxObjectSizeLimit.setVisible(false);
    }

    saveProject.setEnabled(false);
    initPluginOptions(result);
    initProjectActions(result);
  }

  private void initPluginOptions(ConfigInfo info) {
    pluginOptionsPanel.clear();
    pluginConfigWidgets = new HashMap<>();

    for (String pluginName : info.pluginConfig().keySet()) {
      Map<String, HasEnabled> widgetMap = new HashMap<>();
      pluginConfigWidgets.put(pluginName, widgetMap);
      LabeledWidgetsGrid g = new LabeledWidgetsGrid();
      g.addHeader(new SmallHeading(AdminMessages.I.pluginProjectOptionsTitle(pluginName)));
      pluginOptionsPanel.add(g);
      NativeMap<ConfigParameterInfo> pluginConfig = info.pluginConfig(pluginName);
      pluginConfig.copyKeysIntoChildren("name");
      for (ConfigParameterInfo param : Natives.asList(pluginConfig.values())) {
        HasEnabled w;
        switch (param.type()) {
          case "STRING":
          case "INT":
          case "LONG":
            w = renderTextBox(g, param);
            break;
          case "BOOLEAN":
            w = renderCheckBox(g, param);
            break;
          case "LIST":
            w = renderListBox(g, param);
            break;
          case "ARRAY":
            w = renderStringListPanel(g, param);
            break;
          default:
            throw new UnsupportedOperationException("unsupported widget type");
        }
        if (param.editable()) {
          widgetMap.put(param.name(), w);
        } else {
          w.setEnabled(false);
        }
      }
    }

    enableForm();
  }

  private TextBox renderTextBox(LabeledWidgetsGrid g, ConfigParameterInfo param) {
    NpTextBox textBox = param.type().equals("STRING") ? new NpTextBox() : new NpIntTextBox();
    if (param.inheritable()) {
      textBox.setValue(param.configuredValue());
      Label inheritedLabel =
          new Label(AdminMessages.I.pluginProjectInheritedValue(param.inheritedValue()));
      inheritedLabel.setStyleName(Gerrit.RESOURCES.css().pluginProjectConfigInheritedValue());
      HorizontalPanel p = new HorizontalPanel();
      p.add(textBox);
      p.add(inheritedLabel);
      addWidget(g, p, param);
    } else {
      textBox.setValue(param.value());
      addWidget(g, textBox, param);
    }
    saveEnabler.listenTo(textBox);
    return textBox;
  }

  private CheckBox renderCheckBox(LabeledWidgetsGrid g, ConfigParameterInfo param) {
    CheckBox checkBox = new CheckBox(getDisplayName(param));
    checkBox.setValue(Boolean.parseBoolean(param.value()));
    HorizontalPanel p = new HorizontalPanel();
    p.add(checkBox);
    if (param.description() != null) {
      Image infoImg = new Image(Gerrit.RESOURCES.info());
      infoImg.setTitle(param.description());
      p.add(infoImg);
    }
    if (param.warning() != null) {
      Image warningImg = new Image(Gerrit.RESOURCES.warning());
      warningImg.setTitle(param.warning());
      p.add(warningImg);
    }
    g.add((String) null, p);
    saveEnabler.listenTo(checkBox);
    return checkBox;
  }

  private ListBox renderListBox(LabeledWidgetsGrid g, ConfigParameterInfo param) {
    if (param.permittedValues() == null) {
      return null;
    }
    ListBox listBox = new ListBox();
    if (param.inheritable()) {
      listBox.addItem(AdminMessages.I.pluginProjectInheritedListValue(param.inheritedValue()));
      if (param.configuredValue() == null) {
        listBox.setSelectedIndex(0);
      }
      for (int i = 0; i < param.permittedValues().length(); i++) {
        String pv = param.permittedValues().get(i);
        listBox.addItem(pv);
        if (pv.equals(param.configuredValue())) {
          listBox.setSelectedIndex(i + 1);
        }
      }
    } else {
      for (int i = 0; i < param.permittedValues().length(); i++) {
        String pv = param.permittedValues().get(i);
        listBox.addItem(pv);
        if (pv.equals(param.value())) {
          listBox.setSelectedIndex(i);
        }
      }
    }

    if (param.editable()) {
      saveEnabler.listenTo(listBox);
      addWidget(g, listBox, param);
    } else {
      listBox.setEnabled(false);

      if (param.inheritable() && listBox.getSelectedIndex() != 0) {
        // the inherited value is not selected,
        // since the listBox is disabled the inherited value cannot be
        // seen and we have to display it explicitly
        Label inheritedLabel =
            new Label(AdminMessages.I.pluginProjectInheritedValue(param.inheritedValue()));
        inheritedLabel.setStyleName(Gerrit.RESOURCES.css().pluginProjectConfigInheritedValue());
        HorizontalPanel p = new HorizontalPanel();
        p.add(listBox);
        p.add(inheritedLabel);
        addWidget(g, p, param);
      } else {
        addWidget(g, listBox, param);
      }
    }

    return listBox;
  }

  private StringListPanel renderStringListPanel(LabeledWidgetsGrid g, ConfigParameterInfo param) {
    StringListPanel p =
        new StringListPanel(null, Arrays.asList(getDisplayName(param)), saveProject, false);
    List<List<String>> values = new ArrayList<>();
    for (String v : Natives.asList(param.values())) {
      values.add(Arrays.asList(v));
    }
    p.display(values);
    if (!param.editable()) {
      p.setEnabled(false);
    }
    addWidget(g, p, param);
    return p;
  }

  private void addWidget(LabeledWidgetsGrid g, Widget w, ConfigParameterInfo param) {
    if (param.description() != null || param.warning() != null) {
      HorizontalPanel p = new HorizontalPanel();
      p.add(new Label(getDisplayName(param)));
      if (param.description() != null) {
        Image infoImg = new Image(Gerrit.RESOURCES.info());
        infoImg.setTitle(param.description());
        p.add(infoImg);
      }
      if (param.warning() != null) {
        Image warningImg = new Image(Gerrit.RESOURCES.warning());
        warningImg.setTitle(param.warning());
        p.add(warningImg);
      }
      p.add(new Label(":"));
      g.add(p, w);
    } else {
      g.add(getDisplayName(param), w);
    }
  }

  private String getDisplayName(ConfigParameterInfo param) {
    return param.displayName() != null ? param.displayName() : param.name();
  }

  private void initProjectActions(ConfigInfo info) {
    actionsGrid.clear(true);
    actionsGrid.removeAllRows();
    boolean showCreateChange = Gerrit.isSignedIn();

    NativeMap<ActionInfo> actions = info.actions();
    if (actions == null) {
      actions = NativeMap.create().cast();
    }
    if (actions.isEmpty() && !showCreateChange) {
      return;
    }
    actions.copyKeysIntoChildren("id");
    actionsGrid.addHeader(new SmallHeading(AdminConstants.I.headingProjectCommands()));
    FlowPanel actionsPanel = new FlowPanel();
    actionsPanel.setStyleName(Gerrit.RESOURCES.css().projectActions());
    actionsPanel.setVisible(true);
    actionsGrid.add(AdminConstants.I.headingCommands(), actionsPanel);

    for (String id : actions.keySet()) {
      actionsPanel.add(new ActionButton(getProjectKey(), actions.get(id)));
    }

    // TODO: The user should have create permission on the branch referred to by
    // HEAD. This would have to happen on the server side.
    if (showCreateChange) {
      actionsPanel.add(createChangeAction());
    }

    if (isOwner && configVisible) {
      actionsPanel.add(createEditConfigAction());
    }
  }

  private Button createChangeAction() {
    final Button createChange = new Button(AdminConstants.I.buttonCreateChange());
    createChange.setStyleName("");
    createChange.setTitle(AdminConstants.I.buttonCreateChangeDescription());
    createChange.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            CreateChangeAction.call(createChange, getProjectKey().get());
          }
        });
    return createChange;
  }

  private Button createEditConfigAction() {
    final Button editConfig = new Button(AdminConstants.I.buttonEditConfig());
    editConfig.setStyleName("");
    editConfig.setTitle(AdminConstants.I.buttonEditConfigDescription());
    editConfig.addClickHandler(
        new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            EditConfigAction.call(editConfig, getProjectKey());
          }
        });
    return editConfig;
  }

  private void doSave() {
    enableForm(false);
    saveProject.setEnabled(false);
    InheritableBoolean esp = enableSignedPush != null ? getBool(enableSignedPush) : null;
    InheritableBoolean rsp = requireSignedPush != null ? getBool(requireSignedPush) : null;
    ProjectApi.setConfig(
        getProjectKey(),
        descTxt.getText().trim(),
        getBool(contributorAgreements),
        getBool(contentMerge),
        getBool(signedOffBy),
        getBool(newChangeForAllNotInTarget),
        getBool(requireChangeID),
        esp,
        rsp,
        getBool(rejectImplicitMerges),
        getBool(privateByDefault),
        getBool(workInProgressByDefault),
        getBool(enableReviewerByEmail),
        getBool(matchAuthorToCommitterDate),
        maxObjectSizeLimit.getText().trim(),
        SubmitType.valueOf(submitType.getValue(submitType.getSelectedIndex())),
        ProjectState.valueOf(state.getValue(state.getSelectedIndex())),
        getPluginConfigValues(),
        new GerritCallback<ConfigInfo>() {
          @Override
          public void onSuccess(ConfigInfo result) {
            enableForm();
            display(result);
          }

          @Override
          public void onFailure(Throwable caught) {
            enableForm();
            super.onFailure(caught);
          }
        });
  }

  private Map<String, Map<String, ConfigParameterValue>> getPluginConfigValues() {
    Map<String, Map<String, ConfigParameterValue>> pluginConfigValues =
        new HashMap<>(pluginConfigWidgets.size());
    for (Entry<String, Map<String, HasEnabled>> e : pluginConfigWidgets.entrySet()) {
      Map<String, ConfigParameterValue> values = new HashMap<>(e.getValue().size());
      pluginConfigValues.put(e.getKey(), values);
      for (Entry<String, HasEnabled> e2 : e.getValue().entrySet()) {
        HasEnabled widget = e2.getValue();
        if (widget instanceof TextBox) {
          values.put(
              e2.getKey(),
              ConfigParameterValue.create().value(((TextBox) widget).getValue().trim()));
        } else if (widget instanceof CheckBox) {
          values.put(
              e2.getKey(),
              ConfigParameterValue.create()
                  .value(Boolean.toString(((CheckBox) widget).getValue())));
        } else if (widget instanceof ListBox) {
          ListBox listBox = (ListBox) widget;
          // the inherited value is at index 0,
          // if it is selected no value should be set on this project
          String value =
              listBox.getSelectedIndex() > 0 ? listBox.getValue(listBox.getSelectedIndex()) : null;
          values.put(e2.getKey(), ConfigParameterValue.create().value(value));
        } else if (widget instanceof StringListPanel) {
          values.put(
              e2.getKey(),
              ConfigParameterValue.create()
                  .values(((StringListPanel) widget).getValues(0).toArray(new String[] {})));
        } else {
          throw new UnsupportedOperationException("unsupported widget type");
        }
      }
    }
    return pluginConfigValues;
  }

  public static class ProjectDownloadPanel extends DownloadPanel {
    public ProjectDownloadPanel(String project, boolean isAllowsAnonymous) {
      super(project, isAllowsAnonymous);
    }

    @Override
    protected List<DownloadCommandInfo> getCommands(DownloadSchemeInfo schemeInfo) {
      return schemeInfo.cloneCommands(project);
    }
  }

  private static class LabeledWidgetsGrid extends FlexTable {
    private String labelSuffix;

    LabeledWidgetsGrid() {
      super();
      labelSuffix = ":";
    }

    private void addHeader(Widget widget) {
      int row = getRowCount();
      insertRow(row);
      setWidget(row, 0, widget);
      getCellFormatter().getElement(row, 0).setAttribute("colSpan", "2");
    }

    private void add(String label, boolean labelIsHtml, Widget widget) {
      int row = getRowCount();
      insertRow(row);
      if (label != null) {
        if (labelIsHtml) {
          setHTML(row, 0, label + labelSuffix);
        } else {
          setText(row, 0, label + labelSuffix);
        }
      }
      setWidget(row, 1, widget);
    }

    public void add(String label, Widget widget) {
      add(label, false, widget);
    }

    public void addHtml(String label, Widget widget) {
      add(label, true, widget);
    }

    public void add(Widget label, Widget widget) {
      int row = getRowCount();
      insertRow(row);
      setWidget(row, 0, label);
      setWidget(row, 1, widget);
    }
  }
}
