// 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.Dispatcher;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.VoidResult;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.groups.GroupApi;
import com.google.gerrit.client.groups.GroupInfo;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.AccountGroupSuggestOracle;
import com.google.gerrit.client.ui.AccountLinkPanel;
import com.google.gerrit.client.ui.AddMemberBox;
import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gerrit.client.ui.Hyperlink;
import com.google.gerrit.client.ui.SmallHeading;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
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.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Panel;

import java.util.Comparator;
import java.util.HashSet;
import java.util.List;

public class AccountGroupMembersScreen extends AccountGroupScreen {

  private MemberTable members;
  private IncludeTable includes;

  private Panel memberPanel;
  private AddMemberBox addMemberBox;
  private Button delMember;

  private Panel includePanel;
  private AddMemberBox addIncludeBox;
  private Button delInclude;

  private FlowPanel noMembersInfo;
  private AccountGroupSuggestOracle accountGroupSuggestOracle;

  public AccountGroupMembersScreen(final GroupInfo toShow, final String token) {
    super(toShow, token);
  }

  @Override
  protected void onInitUI() {
    super.onInitUI();
    initMemberList();
    initIncludeList();
    initNoMembersInfo();
  }

  private void enableForm(final boolean canModify) {
    addMemberBox.setEnabled(canModify);
    members.setEnabled(canModify);
    addIncludeBox.setEnabled(canModify);
    includes.setEnabled(canModify);
  }


  private void initMemberList() {
    addMemberBox = new AddMemberBox();

    addMemberBox.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        doAddNewMember();
      }
    });

    members = new MemberTable();
    members.addStyleName(Gerrit.RESOURCES.css().groupMembersTable());

    delMember = new Button(Util.C.buttonDeleteGroupMembers());
    delMember.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        members.deleteChecked();
      }
    });

    memberPanel = new FlowPanel();
    memberPanel.add(new SmallHeading(Util.C.headingMembers()));
    memberPanel.add(addMemberBox);
    memberPanel.add(members);
    memberPanel.add(delMember);
    add(memberPanel);
  }

  private void initIncludeList() {
    accountGroupSuggestOracle = new AccountGroupSuggestOracle();
    addIncludeBox =
        new AddMemberBox(Util.C.buttonAddIncludedGroup(),
            Util.C.defaultAccountGroupName(), accountGroupSuggestOracle);

    addIncludeBox.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        doAddNewInclude();
      }
    });

    includes = new IncludeTable();
    includes.addStyleName(Gerrit.RESOURCES.css().groupIncludesTable());

    delInclude = new Button(Util.C.buttonDeleteIncludedGroup());
    delInclude.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        includes.deleteChecked();
      }
    });

    includePanel = new FlowPanel();
    includePanel.add(new SmallHeading(Util.C.headingIncludedGroups()));
    includePanel.add(addIncludeBox);
    includePanel.add(includes);
    includePanel.add(delInclude);
    add(includePanel);
  }

  private void initNoMembersInfo() {
    noMembersInfo = new FlowPanel();
    noMembersInfo.setVisible(false);
    noMembersInfo.add(new SmallHeading(Util.C.noMembersInfo()));
    add(noMembersInfo);
  }

  @Override
  protected void display(final GroupInfo group, final boolean canModify) {
    if (AccountGroup.isInternalGroup(group.getGroupUUID())) {
      members.display(Natives.asList(group.members()));
      includes.display(Natives.asList(group.includes()));
    } else {
      memberPanel.setVisible(false);
      includePanel.setVisible(false);
      noMembersInfo.setVisible(true);
    }

    enableForm(canModify);
    delMember.setVisible(canModify);
    delInclude.setVisible(canModify);
  }

  void doAddNewMember() {
    final String nameEmail = addMemberBox.getText();
    if (nameEmail.length() == 0) {
      return;
    }

    addMemberBox.setEnabled(false);
    GroupApi.addMember(getGroupUUID(), nameEmail,
        new GerritCallback<AccountInfo>() {
          public void onSuccess(final AccountInfo memberInfo) {
            addMemberBox.setEnabled(true);
            addMemberBox.setText("");
            members.insert(memberInfo);
          }

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

  void doAddNewInclude() {
    String groupName = addIncludeBox.getText();
    if (groupName.length() == 0) {
      return;
    }

    AccountGroup.UUID uuid = accountGroupSuggestOracle.getUUID(groupName);
    if (uuid == null) {
      return;
    }

    addIncludeBox.setEnabled(false);
    GroupApi.addIncludedGroup(getGroupUUID(), uuid.get(),
        new GerritCallback<GroupInfo>() {
          public void onSuccess(final GroupInfo result) {
            addIncludeBox.setEnabled(true);
            addIncludeBox.setText("");
            includes.insert(result);
          }

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

  private class MemberTable extends FancyFlexTable<AccountInfo> {
    private boolean enabled = true;

    MemberTable() {
      table.setText(0, 2, Util.C.columnMember());
      table.setText(0, 3, Util.C.columnEmailAddress());

      final FlexCellFormatter fmt = table.getFlexCellFormatter();
      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
    }

    void setEnabled(final boolean enabled) {
      this.enabled = enabled;
      for (int row = 1; row < table.getRowCount(); row++) {
        final AccountInfo i = getRowItem(row);
        if (i != null) {
          ((CheckBox) table.getWidget(row, 1)).setEnabled(enabled);
        }
      }
    }

    void deleteChecked() {
      final HashSet<Integer> ids = new HashSet<>();
      for (int row = 1; row < table.getRowCount(); row++) {
        final AccountInfo i = getRowItem(row);
        if (i != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
          ids.add(i._account_id());
        }
      }
      if (!ids.isEmpty()) {
        GroupApi.removeMembers(getGroupUUID(), ids,
            new GerritCallback<VoidResult>() {
              public void onSuccess(final VoidResult result) {
                for (int row = 1; row < table.getRowCount();) {
                  final AccountInfo i = getRowItem(row);
                  if (i != null && ids.contains(i._account_id())) {
                    table.removeRow(row);
                  } else {
                    row++;
                  }
                }
              }
            });
      }
    }

    void display(final List<AccountInfo> result) {
      while (1 < table.getRowCount())
        table.removeRow(table.getRowCount() - 1);

      for (final AccountInfo i : result) {
        final int row = table.getRowCount();
        table.insertRow(row);
        applyDataRowStyle(row);
        populate(row, i);
      }
    }

    void insert(AccountInfo info) {
      Comparator<AccountInfo> c = new Comparator<AccountInfo>() {
        @Override
        public int compare(AccountInfo a, AccountInfo b) {
          int cmp = nullToEmpty(a.name()).compareTo(nullToEmpty(b.name()));
          if (cmp != 0) {
            return cmp;
          }

          cmp = nullToEmpty(a.email()).compareTo(nullToEmpty(b.email()));
          if (cmp != 0) {
            return cmp;
          }

          return a._account_id() - b._account_id();
        }

        public String nullToEmpty(String str) {
          return str == null ? "" : str;
        }
      };
      int insertPos = getInsertRow(c, info);
      if (insertPos >= 0) {
        table.insertRow(insertPos);
        applyDataRowStyle(insertPos);
        populate(insertPos, info);
      }
    }

    void populate(final int row, final AccountInfo i) {
      CheckBox checkBox = new CheckBox();
      table.setWidget(row, 1, checkBox);
      checkBox.setEnabled(enabled);
      table.setWidget(row, 2, new AccountLinkPanel(i));
      table.setText(row, 3, i.email());

      final FlexCellFormatter fmt = table.getFlexCellFormatter();
      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());
      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());

      setRowItem(row, i);
    }
  }

  private class IncludeTable extends FancyFlexTable<GroupInfo> {
    private boolean enabled = true;

    IncludeTable() {
      table.setText(0, 2, Util.C.columnGroupName());
      table.setText(0, 3, Util.C.columnGroupDescription());

      final FlexCellFormatter fmt = table.getFlexCellFormatter();
      fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().iconHeader());
      fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
      fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
    }

    void setEnabled(final boolean enabled) {
      this.enabled = enabled;
      for (int row = 1; row < table.getRowCount(); row++) {
        final GroupInfo i = getRowItem(row);
        if (i != null) {
          ((CheckBox) table.getWidget(row, 1)).setEnabled(enabled);
        }
      }
    }

    void deleteChecked() {
      final HashSet<AccountGroup.UUID> ids = new HashSet<>();
      for (int row = 1; row < table.getRowCount(); row++) {
        final GroupInfo i = getRowItem(row);
        if (i != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
          ids.add(i.getGroupUUID());
        }
      }
      if (!ids.isEmpty()) {
        GroupApi.removeIncludedGroups(getGroupUUID(), ids,
            new GerritCallback<VoidResult>() {
              public void onSuccess(final VoidResult result) {
                for (int row = 1; row < table.getRowCount();) {
                  final GroupInfo i = getRowItem(row);
                  if (i != null && ids.contains(i.getGroupUUID())) {
                    table.removeRow(row);
                  } else {
                    row++;
                  }
                }
              }
            });
      }
    }

    void display(List<GroupInfo> list) {
      while (1 < table.getRowCount())
        table.removeRow(table.getRowCount() - 1);

      for (final GroupInfo i : list) {
        final int row = table.getRowCount();
        table.insertRow(row);
        applyDataRowStyle(row);
        populate(row, i);
      }
    }

    void insert(GroupInfo info) {
      Comparator<GroupInfo> c = new Comparator<GroupInfo>() {
        @Override
        public int compare(GroupInfo a, GroupInfo b) {
          int cmp = nullToEmpty(a.name()).compareTo(nullToEmpty(b.name()));
          if (cmp != 0) {
            return cmp;
          }
          return a.getGroupUUID().compareTo(b.getGroupUUID());
        }

        private String nullToEmpty(@Nullable String str) {
          return (str == null) ? "" : str;
        }
      };
      int insertPos = getInsertRow(c, info);
      if (insertPos >= 0) {
        table.insertRow(insertPos);
        applyDataRowStyle(insertPos);
        populate(insertPos, info);
      }
    }

    void populate(final int row, final GroupInfo i) {
      final FlexCellFormatter fmt = table.getFlexCellFormatter();

      AccountGroup.UUID uuid = i.getGroupUUID();
      CheckBox checkBox = new CheckBox();
      table.setWidget(row, 1, checkBox);
      checkBox.setEnabled(enabled);
      if (AccountGroup.isInternalGroup(uuid)) {
        table.setWidget(row, 2,
            new Hyperlink(i.name(), Dispatcher.toGroup(uuid)));
        fmt.getElement(row, 2).setTitle(null);
        table.setText(row, 3, i.description());
      } else if (i.url() != null) {
        Anchor a = new Anchor();
        a.setText(i.name());
        a.setHref(i.url());
        a.setTitle("UUID " + uuid.get());
        table.setWidget(row, 2, a);
        fmt.getElement(row, 2).setTitle(null);
      } else {
        table.setText(row, 2, i.name());
        fmt.getElement(row, 2).setTitle("UUID " + uuid.get());
      }

      fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().iconCell());
      fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
      fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());

      setRowItem(row, i);
    }
  }
}
