// 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 static com.google.gerrit.common.data.Permission.EDIT_TOPIC_NAME;
import static com.google.gerrit.common.data.Permission.PUSH;
import static com.google.gerrit.common.data.Permission.PUSH_TAG;

import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.ui.Hyperlink;
import com.google.gerrit.common.data.AccessSection;
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.reviewdb.client.AccountGroup;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.DivElement;
import com.google.gwt.dom.client.SpanElement;
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.event.dom.client.ClickEvent;
import com.google.gwt.text.shared.Renderer;
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.DOM;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.ValueListBox;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

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

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

  @UiField(provided = true)
  ValueListBox<PermissionRule.Action> action;

  @UiField(provided = true)
  RangeBox min;

  @UiField(provided = true)
  RangeBox max;

  @UiField
  CheckBox force;

  @UiField
  Hyperlink groupNameLink;
  @UiField
  SpanElement groupNameSpan;
  @UiField
  SpanElement deletedGroupName;

  @UiField
  Anchor deleteRule;

  @UiField
  DivElement normal;
  @UiField
  DivElement deleted;

  @UiField
  SpanElement rangeEditor;

  private boolean isDeleted;

  public PermissionRuleEditor(boolean readOnly, AccessSection section,
      Permission permission, PermissionRange.WithDefaults validRange) {
    action = new ValueListBox<PermissionRule.Action>(actionRenderer);

    if (validRange != null && 10 < validRange.getRangeSize()) {
        min = new RangeBox.Box();
        max = new RangeBox.Box();

    } else if (validRange != null) {
      RangeBox.List minList = new RangeBox.List();
      RangeBox.List maxList = new RangeBox.List();
      List<Integer> valueList = validRange.getValuesAsList();

      minList.list.setValue(validRange.getMin());
      maxList.list.setValue(validRange.getMax());

      minList.list.setAcceptableValues(valueList);
      maxList.list.setAcceptableValues(valueList);

      min = minList;
      max = maxList;

    } else {
      min = new RangeBox.Box();
      max = new RangeBox.Box();

      if (GlobalCapability.PRIORITY.equals(permission.getName())) {
        action.setValue(PermissionRule.Action.INTERACTIVE);
        action.setAcceptableValues(Arrays.asList(
            PermissionRule.Action.INTERACTIVE,
            PermissionRule.Action.BATCH));

      } else {
        action.setValue(PermissionRule.Action.ALLOW);
        action.setAcceptableValues(Arrays.asList(
            PermissionRule.Action.ALLOW,
            PermissionRule.Action.DENY,
            PermissionRule.Action.BLOCK));
      }
    }

    initWidget(uiBinder.createAndBindUi(this));

    String name = permission.getName();
    boolean canForce = PUSH.equals(name) || PUSH_TAG.equals(name);
    if (canForce) {
      String ref = section.getName();
      canForce = !ref.startsWith("refs/for/") && !ref.startsWith("^refs/for/");
      force.setText(PermissionRule.FORCE_PUSH);
    } else {
      canForce = EDIT_TOPIC_NAME.equals(name);
      force.setText(PermissionRule.FORCE_EDIT);
    }
    force.setVisible(canForce);
    force.setEnabled(!readOnly);

    if (validRange != null) {
      min.setEnabled(!readOnly);
      max.setEnabled(!readOnly);
      action.getElement().getStyle().setDisplay(Display.NONE);

    } else {
      rangeEditor.getStyle().setDisplay(Display.NONE);
      DOM.setElementPropertyBoolean(action.getElement(), "disabled", readOnly);
    }

    if (readOnly) {
      deleteRule.removeFromParent();
      deleteRule = null;
    }
  }

  boolean isDeleted() {
    return isDeleted;
  }

  @UiHandler("deleteRule")
  void onDeleteRule(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);
  }

  @Override
  public void setValue(PermissionRule value) {
    GroupReference ref = value.getGroup();

    boolean link;
    if (ref.getUUID() != null && AccountGroup.isInternalGroup(ref.getUUID())) {
      groupNameLink.setText(ref.getName());
      groupNameLink.setTargetHistoryToken(Dispatcher.toGroup(ref.getUUID()));
      link = true;
    } else {
      groupNameSpan.setInnerText(ref.getName());
      groupNameSpan.setTitle(ref.getUUID() != null ? ref.getUUID().get() : "");
      link = false;
    }

    deletedGroupName.setInnerText(ref.getName());
    groupNameLink.setVisible(link);
    UIObject.setVisible(groupNameSpan, !link);
  }

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

  @Override
  public void flush() {
  }

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

  private static class ActionRenderer implements
      Renderer<PermissionRule.Action> {
    @Override
    public String render(PermissionRule.Action object) {
      return object != null ? object.toString() : "";
    }

    @Override
    public void render(PermissionRule.Action object, Appendable appendable)
        throws IOException {
      appendable.append(render(object));
    }
  }

  private static final ActionRenderer actionRenderer = new ActionRenderer();
}
