// Copyright (C) 2011 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.SuggestUtil;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.PermissionRange;
import com.google.gerrit.common.data.PermissionRule;
import com.google.gerrit.common.data.RefConfigSection;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.EditorDelegate;
import com.google.gwt.editor.client.ValueAwareEditor;
import com.google.gwt.editor.client.adapters.EditorSource;
import com.google.gwt.editor.client.adapters.ListEditor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Anchor;
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.HTMLPanel;
import com.google.gwt.user.client.ui.ValueLabel;

import java.util.ArrayList;
import java.util.List;

public class PermissionEditor extends Composite implements Editor<Permission>,
    ValueAwareEditor<Permission> {
  interface Binder extends UiBinder<HTMLPanel, PermissionEditor> {
  }

  private static final Binder uiBinder = GWT.create(Binder.class);

  @UiField(provided = true)
  @Path("name")
  ValueLabel<String> normalName;

  @UiField(provided = true)
  @Path("name")
  ValueLabel<String> deletedName;

  @UiField
  CheckBox exclusiveGroup;

  @UiField
  FlowPanel ruleContainer;
  ListEditor<PermissionRule, PermissionRuleEditor> rules;

  @UiField
  DivElement addContainer;
  @UiField
  DivElement addStage1;
  @UiField
  DivElement addStage2;
  @UiField
  Anchor beginAddRule;
  @UiField
  @Editor.Ignore
  GroupReferenceBox groupToAdd;
  @UiField
  Button addRule;

  @UiField
  Anchor deletePermission;

  @UiField
  DivElement normal;
  @UiField
  DivElement deleted;

  private final boolean readOnly;
  private final AccessSection section;
  private Permission value;
  private PermissionRange.WithDefaults validRange;
  private boolean isDeleted;

  public PermissionEditor(boolean readOnly, AccessSection section) {
    this.readOnly = readOnly;
    this.section = section;

    normalName = new ValueLabel<String>(PermissionNameRenderer.INSTANCE);
    deletedName = new ValueLabel<String>(PermissionNameRenderer.INSTANCE);

    initWidget(uiBinder.createAndBindUi(this));
    rules = ListEditor.of(new RuleEditorSource());

    exclusiveGroup.setEnabled(!readOnly);
    exclusiveGroup.setVisible(RefConfigSection
        .isValid(section.getName()));

    if (readOnly) {
      addContainer.removeFromParent();
      addContainer = null;

      deletePermission.removeFromParent();
      deletePermission = null;
    }
  }

  @UiHandler("deletePermission")
  void onDeleteHover(MouseOverEvent event) {
    addStyleName(AdminResources.I.css().deleteSectionHover());
  }

  @UiHandler("deletePermission")
  void onDeleteNonHover(MouseOutEvent event) {
    removeStyleName(AdminResources.I.css().deleteSectionHover());
  }

  @UiHandler("deletePermission")
  void onDeletePermission(ClickEvent event) {
    isDeleted = true;
    normal.getStyle().setDisplay(Display.NONE);
    deleted.getStyle().setDisplay(Display.BLOCK);
  }

  @UiHandler("undoDelete")
  void onUndoDelete(ClickEvent event) {
    isDeleted = false;
    deleted.getStyle().setDisplay(Display.NONE);
    normal.getStyle().setDisplay(Display.BLOCK);
  }

  @UiHandler("beginAddRule")
  void onBeginAddRule(ClickEvent event) {
    beginAddRule();
  }

  void beginAddRule() {
    addStage1.getStyle().setDisplay(Display.NONE);
    addStage2.getStyle().setDisplay(Display.BLOCK);

    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
      @Override
      public void execute() {
        groupToAdd.setFocus(true);
      }
    });
  }

  @UiHandler("addRule")
  void onAddGroupByClick(ClickEvent event) {
    GroupReference ref = groupToAdd.getValue();
    if (ref != null) {
      addGroup(ref);
    } else {
      groupToAdd.setFocus(true);
    }
  }

  @UiHandler("groupToAdd")
  void onAddGroupByEnter(SelectionEvent<GroupReference> event) {
    GroupReference ref = event.getSelectedItem();
    if (ref != null) {
      addGroup(ref);
    }
  }

  @UiHandler("groupToAdd")
  void onAbortAddGroup(CloseEvent<GroupReferenceBox> event) {
    hideAddGroup();
  }

  @UiHandler("hideAddGroup")
  void hideAddGroup(ClickEvent event) {
    hideAddGroup();
  }

  private void hideAddGroup() {
    addStage1.getStyle().setDisplay(Display.BLOCK);
    addStage2.getStyle().setDisplay(Display.NONE);
  }

  private void addGroup(GroupReference ref) {
    if (ref.getUUID() != null) {
      if (value.getRule(ref) == null) {
        PermissionRule newRule = value.getRule(ref, true);
        if (validRange != null) {
          int min = validRange.getDefaultMin();
          int max = validRange.getDefaultMax();
          newRule.setRange(min, max);

        } else if (GlobalCapability.PRIORITY.equals(value.getName())) {
          newRule.setAction(PermissionRule.Action.BATCH);
        }

        rules.getList().add(newRule);
      }
      groupToAdd.setValue(null);
      groupToAdd.setFocus(true);

    } else {
      // If the oracle didn't get to complete a UUID, resolve it now.
      //
      addRule.setEnabled(false);
      SuggestUtil.SVC.suggestAccountGroup(ref.getName(), 1,
          new GerritCallback<List<GroupReference>>() {
            @Override
            public void onSuccess(List<GroupReference> result) {
              addRule.setEnabled(true);
              if (result.size() == 1) {
                addGroup(result.get(0));
              } else {
                groupToAdd.setFocus(true);
              }
            }

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

  boolean isDeleted() {
    return isDeleted;
  }

  @Override
  public void setValue(Permission value) {
    this.value = value;

    if (value.isLabel()) {
      ApprovalType at = Gerrit.getConfig().getApprovalTypes().byLabel(value.getLabel());
      if (at != null) {
        validRange = new PermissionRange.WithDefaults(
            value.getName(),
            at.getMin().getValue(), at.getMax().getValue(),
            at.getMin().getValue(), at.getMax().getValue());
      }
    } else if (GlobalCapability.isCapability(value.getName())) {
      validRange = GlobalCapability.getRange(value.getName());

    } else {
      validRange = null;
    }

    if (value != null && Permission.OWNER.equals(value.getName())) {
      exclusiveGroup.setEnabled(false);
    } else {
      exclusiveGroup.setEnabled(!readOnly);
    }
  }

  @Override
  public void flush() {
    List<PermissionRule> src = rules.getList();
    List<PermissionRule> keep = new ArrayList<PermissionRule>(src.size());

    for (int i = 0; i < src.size(); i++) {
      PermissionRuleEditor e =
          (PermissionRuleEditor) ruleContainer.getWidget(i);
      if (!e.isDeleted()) {
        keep.add(src.get(i));
      }
    }
    value.setRules(keep);
  }

  @Override
  public void onPropertyChange(String... paths) {
  }

  @Override
  public void setDelegate(EditorDelegate<Permission> delegate) {
  }

  private class RuleEditorSource extends EditorSource<PermissionRuleEditor> {
    @Override
    public PermissionRuleEditor create(int index) {
      PermissionRuleEditor subEditor =
          new PermissionRuleEditor(readOnly, section, value, validRange);
      ruleContainer.insert(subEditor, index);
      return subEditor;
    }

    @Override
    public void dispose(PermissionRuleEditor subEditor) {
      subEditor.removeFromParent();
    }

    @Override
    public void setIndex(PermissionRuleEditor subEditor, int index) {
      ruleContainer.insert(subEditor, index);
    }
  }
}
