// 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.LabelType;
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>(
        new PermissionNameRenderer(access.getCapabilities()));
    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 : projectAccess.getCapabilities().keySet()) {
        addPermission(varName, perms);
      }
    } else if (RefConfigSection.isValid(value.getName())) {
      for (LabelType t : projectAccess.getLabelTypes().getLabelTypes()) {
        addPermission(Permission.forLabel(t.getName()), perms);
      }
      for (LabelType t : projectAccess.getLabelTypes().getLabelTypes()) {
        addPermission(Permission.forLabelAs(t.getName()), 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, readOnly, value,
              projectAccess.getLabelTypes());
      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);
    }
  }
}
