// 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.common.data.AccessSection;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.Permission;
import com.google.gerrit.common.data.ProjectAccess;
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.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.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.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
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.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.ValueListBox;

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

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

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

  @UiField
  ValueEditor<String> name;

  @UiField
  FlowPanel permissionContainer;
  ListEditor<Permission, PermissionEditor> permissions;

  @UiField
  DivElement addContainer;
  @UiField(provided = true)
  @Editor.Ignore
  ValueListBox<String> permissionSelector;

  @UiField
  SpanElement deletedName;

  @UiField
  Anchor deleteSection;

  @UiField
  DivElement normal;
  @UiField
  DivElement deleted;

  @UiField
  SpanElement sectionType;
  @UiField
  SpanElement sectionName;

  private final ProjectAccess projectAccess;
  private AccessSection value;
  private boolean editing;
  private boolean readOnly;
  private boolean isDeleted;

  public AccessSectionEditor(ProjectAccess access) {
    projectAccess = access;

    permissionSelector =
        new ValueListBox<String>(PermissionNameRenderer.INSTANCE);
    permissionSelector.addValueChangeHandler(new ValueChangeHandler<String>() {
      @Override
      public void onValueChange(ValueChangeEvent<String> event) {
        if (!Util.C.addPermission().equals(event.getValue())) {
          onAddPermission(event.getValue());
        }
      }
    });

    initWidget(uiBinder.createAndBindUi(this));
    permissions = ListEditor.of(new PermissionEditorSource());
  }

  @UiHandler("deleteSection")
  void onDeleteHover(MouseOverEvent event) {
    normal.addClassName(AdminResources.I.css().deleteSectionHover());
  }

  @UiHandler("deleteSection")
  void onDeleteNonHover(MouseOutEvent event) {
    normal.removeClassName(AdminResources.I.css().deleteSectionHover());
  }

  @UiHandler("deleteSection")
  void onDeleteSection(ClickEvent event) {
    isDeleted = true;

    if (name.isVisible()
        && RefConfigSection.isValid(name.getValue())) {
      deletedName.setInnerText(Util.M.deletedReference(name.getValue()));

    } else {
      String name = Util.C.sectionNames().get(value.getName());
      if (name == null) {
        name = value.getName();
      }
      deletedName.setInnerText(Util.M.deletedSection(name));
    }

    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);
  }

  void onAddPermission(String varName) {
    int idx = permissions.getList().size();

    Permission p = value.getPermission(varName, true);
    permissions.getList().add(p);

    PermissionEditor e = permissions.getEditors().get(idx);
    e.beginAddRule();

    rebuildPermissionSelector();
  }

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

  void enableEditing() {
    readOnly = false;
    addContainer.getStyle().setDisplay(Display.BLOCK);
    rebuildPermissionSelector();
  }

  boolean isDeleted() {
    return isDeleted;
  }

  @Override
  public void setValue(AccessSection value) {
    Collections.sort(value.getPermissions());

    this.value = value;
    this.readOnly = !editing || !(projectAccess.isOwnerOf(value) || projectAccess.canUpload());

    name.setEnabled(!readOnly);
    deleteSection.setVisible(!readOnly);

    if (RefConfigSection.isValid(value.getName())) {
      name.setVisible(true);
      name.setIgnoreEditorValue(false);
      sectionType.setInnerText(Util.C.sectionTypeReference());

    } else {
      name.setVisible(false);
      name.setIgnoreEditorValue(true);

      String name = Util.C.sectionNames().get(value.getName());
      if (name != null) {
        sectionType.setInnerText(name);
        sectionName.getStyle().setDisplay(Display.NONE);
      } else {
        sectionType.setInnerText(Util.C.sectionTypeSection());
        sectionName.setInnerText(value.getName());
        sectionName.getStyle().clearDisplay();
      }
    }

    if (readOnly) {
      addContainer.getStyle().setDisplay(Display.NONE);
    } else {
      enableEditing();
    }
  }

  void setEditing(final boolean editing) {
    this.editing = editing;
  }

  private void rebuildPermissionSelector() {
    List<String> perms = new ArrayList<String>();

    if (AccessSection.GLOBAL_CAPABILITIES.equals(value.getName())) {
      for (String varName : Util.C.capabilityNames().keySet()) {
        addPermission(varName, perms);
      }
    } else if (RefConfigSection.isValid(value.getName())) {
      for (ApprovalType t : Gerrit.getConfig().getApprovalTypes()
          .getApprovalTypes()) {
        String varName = Permission.LABEL + t.getCategory().getLabelName();
        addPermission(varName, perms);
      }
      for (String varName : Util.C.permissionNames().keySet()) {
        addPermission(varName, perms);
      }
    }
    if (perms.isEmpty()) {
      addContainer.getStyle().setDisplay(Display.NONE);
    } else {
      addContainer.getStyle().setDisplay(Display.BLOCK);
      perms.add(0, Util.C.addPermission());
      permissionSelector.setValue(Util.C.addPermission());
      permissionSelector.setAcceptableValues(perms);
    }
  }

  private void addPermission(final String permissionName,
      final List<String> permissionList) {
    if (value.getPermission(permissionName) != null) {
      return;
    }
    if (Gerrit.getConfig().getWildProject()
        .equals(projectAccess.getProjectName())
        && !Permission.canBeOnAllProjects(value.getName(), permissionName)) {
      return;
    }
    permissionList.add(permissionName);
  }

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

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

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

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

  private class PermissionEditorSource extends EditorSource<PermissionEditor> {
    @Override
    public PermissionEditor create(int index) {
      PermissionEditor subEditor =
          new PermissionEditor(projectAccess.getProjectName(), readOnly, value);
      permissionContainer.insert(subEditor, index);
      return subEditor;
    }

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

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