// Copyright (C) 2010 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.account;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gerrit.client.ui.ProjectLink;
import com.google.gerrit.common.data.AccountProjectWatchInfo;
import com.google.gerrit.reviewdb.client.AccountProjectWatch;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
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.Label;
import com.google.gwtjsonrpc.common.VoidResult;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MyWatchesTable extends FancyFlexTable<AccountProjectWatchInfo> {

  public MyWatchesTable() {
    table.setWidth("");
    table.insertRow(1);
    table.setText(0, 2, Util.C.watchedProjectName());
    table.setText(0, 3, Util.C.watchedProjectColumnEmailNotifications());

    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());
    fmt.setRowSpan(0, 0, 2);
    fmt.setRowSpan(0, 1, 2);
    fmt.setRowSpan(0, 2, 2);
    fmt.getElement(0, 3).setPropertyString("align", "center");

    fmt.setColSpan(0, 3, 5);
    table.setText(1, 0, Util.C.watchedProjectColumnNewChanges());
    table.setText(1, 1, Util.C.watchedProjectColumnNewPatchSets());
    table.setText(1, 2, Util.C.watchedProjectColumnAllComments());
    table.setText(1, 3, Util.C.watchedProjectColumnSubmittedChanges());
    table.setText(1, 4, Util.C.watchedProjectColumnAbandonedChanges());
    fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().dataHeader());
    fmt.addStyleName(1, 1, Gerrit.RESOURCES.css().dataHeader());
    fmt.addStyleName(1, 2, Gerrit.RESOURCES.css().dataHeader());
    fmt.addStyleName(1, 3, Gerrit.RESOURCES.css().dataHeader());
    fmt.addStyleName(1, 4, Gerrit.RESOURCES.css().dataHeader());
  }

  public void deleteChecked() {
    final Set<AccountProjectWatch.Key> ids = getCheckedIds();
    if (!ids.isEmpty()) {
      Util.ACCOUNT_SVC.deleteProjectWatches(ids,
          new GerritCallback<VoidResult>() {
            @Override
            public void onSuccess(final VoidResult result) {
              remove(ids);
            }
          });
    }
  }

  protected void remove(Set<AccountProjectWatch.Key> ids) {
    for (int row = 1; row < table.getRowCount();) {
      final AccountProjectWatchInfo k = getRowItem(row);
      if (k != null && ids.contains(k.getWatch().getKey())) {
        table.removeRow(row);
      } else {
        row++;
      }
    }
  }

  protected Set<AccountProjectWatch.Key> getCheckedIds() {
    final Set<AccountProjectWatch.Key> ids = new HashSet<>();
    for (int row = 1; row < table.getRowCount(); row++) {
      final AccountProjectWatchInfo k = getRowItem(row);
      if (k != null && ((CheckBox) table.getWidget(row, 1)).getValue()) {
        ids.add(k.getWatch().getKey());
      }
    }
    return ids;
  }

  public void insertWatch(final AccountProjectWatchInfo k) {
    final String newName = k.getProject().getName();
    int row = 1;
    for (; row < table.getRowCount(); row++) {
      final AccountProjectWatchInfo i = getRowItem(row);
      if (i != null && i.getProject().getName().compareTo(newName) >= 0) {
        break;
      }
    }

    table.insertRow(row);
    applyDataRowStyle(row);
    populate(row, k);
  }

  public void display(final List<AccountProjectWatchInfo> result) {
    while (2 < table.getRowCount()) {
      table.removeRow(table.getRowCount() - 1);
    }

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

  protected void populate(final int row, final AccountProjectWatchInfo info) {
    final FlowPanel fp = new FlowPanel();
    fp.add(new ProjectLink(info.getProject().getNameKey()));
    if (info.getWatch().getFilter() != null) {
      Label filter = new Label(info.getWatch().getFilter());
      filter.setStyleName(Gerrit.RESOURCES.css().watchedProjectFilter());
      fp.add(filter);
    }

    table.setWidget(row, 1, new CheckBox());
    table.setWidget(row, 2, fp);

    addNotifyButton(AccountProjectWatch.NotifyType.NEW_CHANGES, info, row, 3);
    addNotifyButton(AccountProjectWatch.NotifyType.NEW_PATCHSETS, info, row, 4);
    addNotifyButton(AccountProjectWatch.NotifyType.ALL_COMMENTS, info, row, 5);
    addNotifyButton(AccountProjectWatch.NotifyType.SUBMITTED_CHANGES, info, row, 6);
    addNotifyButton(AccountProjectWatch.NotifyType.ABANDONED_CHANGES, info, row, 7);

    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());
    fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
    fmt.addStyleName(row, 5, Gerrit.RESOURCES.css().dataCell());
    fmt.addStyleName(row, 6, Gerrit.RESOURCES.css().dataCell());
    fmt.addStyleName(row, 7, Gerrit.RESOURCES.css().dataCell());

    setRowItem(row, info);
  }

  protected void addNotifyButton(final AccountProjectWatch.NotifyType type,
      final AccountProjectWatchInfo info, final int row, final int col) {
    final CheckBox cbox = new CheckBox();

    cbox.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        final boolean oldVal = info.getWatch().isNotify(type);
        info.getWatch().setNotify(type, cbox.getValue());
        cbox.setEnabled(false);
        Util.ACCOUNT_SVC.updateProjectWatch(info.getWatch(),
            new GerritCallback<VoidResult>() {
              @Override
              public void onSuccess(final VoidResult result) {
                cbox.setEnabled(true);
              }

              @Override
              public void onFailure(final Throwable caught) {
                cbox.setEnabled(true);
                info.getWatch().setNotify(type, oldVal);
                cbox.setValue(oldVal);
                super.onFailure(caught);
              }
            });
      }
    });

    cbox.setValue(info.getWatch().isNotify(type));
    table.setWidget(row, col, cbox);
  }
}
