// Copyright (C) 2013 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.change;

import static com.google.gerrit.common.PageLinks.op;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ChangeList;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.extensions.client.ListChangesOption;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.event.logical.shared.SelectionHandler;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.TabBar;
import com.google.gwt.user.client.ui.TabPanel;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

public class RelatedChanges extends TabPanel {
  static final RelatedChangesResources R = GWT
      .create(RelatedChangesResources.class);

  interface RelatedChangesResources extends ClientBundle {
    @Source("related_changes.css")
    RelatedChangesCss css();
  }

  interface RelatedChangesCss extends CssResource {
    String activeRow();
    String current();
    String gitweb();
    String indirect();
    String notCurrent();
    String pointer();
    String row();
    String subject();
    String strikedSubject();
    String submittable();
    String tabPanel();
  }

  enum Tab {
    RELATED_CHANGES(Resources.C.relatedChanges(),
        Resources.C.relatedChangesTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.relatedChanges(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.relatedChanges(count);
      }
    },

    SUBMITTED_TOGETHER(Resources.C.submittedTogether(),
        Resources.C.submittedTogether()) {
      @Override
      String getTitle(int count) {
        return Resources.M.submittedTogether(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.submittedTogether(count);
      }
    },

    SAME_TOPIC(Resources.C.sameTopic(),
        Resources.C.sameTopicTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.sameTopic(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.sameTopic(count);
      }
    },

    CONFLICTING_CHANGES(Resources.C.conflictingChanges(),
        Resources.C.conflictingChangesTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.conflictingChanges(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.conflictingChanges(count);
      }
    },

    CHERRY_PICKS(Resources.C.cherryPicks(),
        Resources.C.cherryPicksTooltip()) {
      @Override
      String getTitle(int count) {
        return Resources.M.cherryPicks(count);
      }

      @Override
      String getTitle(String count) {
        return Resources.M.cherryPicks(count);
      }
    };

    final String defaultTitle;
    final String tooltip;

    abstract String getTitle(int count);
    abstract String getTitle(String count);

    Tab(String defaultTitle, String tooltip) {
      this.defaultTitle = defaultTitle;
      this.tooltip = tooltip;
    }
  }

  private static Tab savedTab;

  private final List<RelatedChangesTab> tabs;
  private int maxHeightWithHeader;
  private int selectedTab;
  private int outstandingCallbacks;

  RelatedChanges() {
    tabs = new ArrayList<>(Tab.values().length);
    selectedTab = -1;

    setVisible(false);
    addStyleName(R.css().tabPanel());
    initTabBar();
  }

  private void initTabBar() {
    TabBar tabBar = getTabBar();
    tabBar.addSelectionHandler(new SelectionHandler<Integer>() {
      @Override
      public void onSelection(SelectionEvent<Integer> event) {
        if (selectedTab >= 0) {
          tabs.get(selectedTab).registerKeys(false);
        }
        selectedTab = event.getSelectedItem();
        tabs.get(selectedTab).registerKeys(true);
      }
    });

    for (Tab tabInfo : Tab.values()) {
      RelatedChangesTab panel = new RelatedChangesTab(tabInfo);
      add(panel, tabInfo.defaultTitle);
      tabs.add(panel);

      TabBar.Tab tab = tabBar.getTab(tabInfo.ordinal());
      tab.setWordWrap(false);
      ((Composite) tab).setTitle(tabInfo.tooltip);

      setTabEnabled(tabInfo, false);
    }
    getTab(Tab.RELATED_CHANGES).setShowIndirectAncestors(true);
    getTab(Tab.CHERRY_PICKS).setShowBranches(true);
    getTab(Tab.SAME_TOPIC).setShowBranches(true);
    getTab(Tab.SAME_TOPIC).setShowProjects(true);
    getTab(Tab.SAME_TOPIC).setShowSubmittable(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowBranches(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowProjects(true);
    getTab(Tab.SUBMITTED_TOGETHER).setShowSubmittable(true);
  }

  void set(final ChangeInfo info, final String revision) {
    if (info.status().isOpen()) {
      setForOpenChange(info, revision);
    }

    ChangeApi.revision(info.legacyId().get(), revision).view("related")
        .get(new TabCallback<RelatedInfo>(Tab.RELATED_CHANGES, info.project(), revision) {
              @Override
              public JsArray<ChangeAndCommit> convert(RelatedInfo result) {
                return result.changes();
              }
            });

    StringBuilder cherryPicksQuery = new StringBuilder();
    cherryPicksQuery.append(op("project", info.project()));
    cherryPicksQuery.append(" ").append(op("change", info.changeId()));
    cherryPicksQuery.append(" ").append(op("-change", info.legacyId().get()));
    cherryPicksQuery.append(" -is:abandoned");
    ChangeList.query(cherryPicksQuery.toString(),
        EnumSet.of(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT),
        new TabChangeListCallback(Tab.CHERRY_PICKS, info.project(), revision));

    if (info.currentRevision() != null
        && info.currentRevision().equals(revision)) {
      ChangeApi.change(info.legacyId().get()).view("submitted_together")
          .get(new TabChangeListCallback(Tab.SUBMITTED_TOGETHER,
              info.project(), revision));
    }

    if (!Gerrit.info().change().isSubmitWholeTopicEnabled()
        && info.topic() != null && !"".equals(info.topic())) {
      StringBuilder topicQuery = new StringBuilder();
      topicQuery.append("status:open");
      topicQuery.append(" ").append(op("topic", info.topic()));
      ChangeList.query(topicQuery.toString(),
          EnumSet.of(ListChangesOption.CURRENT_REVISION,
                     ListChangesOption.CURRENT_COMMIT,
                     ListChangesOption.DETAILED_LABELS,
                     ListChangesOption.LABELS),
          new TabChangeListCallback(Tab.SAME_TOPIC, info.project(), revision));
    }
  }

  private void setForOpenChange(final ChangeInfo info, final String revision) {
    if (info.mergeable()) {
      StringBuilder conflictsQuery = new StringBuilder();
      conflictsQuery.append("status:open");
      conflictsQuery.append(" is:mergeable");
      conflictsQuery.append(" ").append(op("conflicts", info.legacyId().get()));
      ChangeList.query(conflictsQuery.toString(),
          EnumSet.of(ListChangesOption.CURRENT_REVISION, ListChangesOption.CURRENT_COMMIT),
          new TabChangeListCallback(Tab.CONFLICTING_CHANGES, info.project(), revision));
    }
  }

  @Override
  protected void onLoad() {
    super.onLoad();
    R.css().ensureInjected();
  }

  static void setSavedTab(Tab subject) {
    savedTab = subject;
  }

  private RelatedChangesTab getTab(Tab tabInfo) {
    return tabs.get(tabInfo.ordinal());
  }

  private void setTabTitle(Tab tabInfo, String title) {
    getTabBar().setTabText(tabInfo.ordinal(), title);
  }

  private void setTabEnabled(Tab tabInfo, boolean enabled) {
    getTabBar().setTabEnabled(tabInfo.ordinal(), enabled);
  }

  void setMaxHeight(int height) {
    maxHeightWithHeader = height;
    if (isVisible()) {
      applyMaxHeight();
    }
  }

  private void applyMaxHeight() {
    int header = getTabBar().getOffsetHeight() + 2 /* padding */;
    for (int i = 0; i < getTabBar().getTabCount(); i++) {
      tabs.get(i).setMaxHeight(maxHeightWithHeader - header);
    }
  }

  private abstract class TabCallback<T> implements AsyncCallback<T> {
    private final Tab tabInfo;
    private final String project;
    private final String revision;

    TabCallback(Tab tabInfo, String project, String revision) {
      this.tabInfo = tabInfo;
      this.project = project;
      this.revision = revision;
      outstandingCallbacks++;
    }

    protected abstract JsArray<ChangeAndCommit> convert(T result);

    @Override
    public void onSuccess(T result) {
      if (isAttached()) {
        JsArray<ChangeAndCommit> changes = convert(result);
        if (changes.length() > 0) {
          setTabTitle(tabInfo, tabInfo.getTitle(changes.length()));
          getTab(tabInfo).setChanges(project, revision, changes);
        }
        onDone(changes.length() > 0);
      }
    }

    @Override
    public void onFailure(Throwable err) {
      if (isAttached()) {
        setTabTitle(tabInfo, tabInfo.getTitle(Resources.C.notAvailable()));
        getTab(tabInfo).setError(err.getMessage());
        onDone(true);
      }
    }

    private void onDone(boolean enabled) {
      setTabEnabled(tabInfo, enabled);
      outstandingCallbacks--;
      if (outstandingCallbacks == 0 || (enabled && tabInfo == Tab.RELATED_CHANGES)) {
        outstandingCallbacks = 0;  // Only execute this block once
        for (int i = 0; i < getTabBar().getTabCount(); i++) {
          if (getTabBar().isTabEnabled(i)) {
            selectTab(i);
            setVisible(true);
            applyMaxHeight();
            break;
          }
        }
      }

      if (tabInfo == savedTab && enabled) {
        selectTab(savedTab.ordinal());
      }
    }
  }

  private class TabChangeListCallback extends TabCallback<ChangeList> {
    TabChangeListCallback(Tab tabInfo, String project, String revision) {
      super(tabInfo, project, revision);
    }

    @Override
    protected JsArray<ChangeAndCommit> convert(ChangeList l) {
      JsArray<ChangeAndCommit> arr = JavaScriptObject.createArray().cast();
      for (ChangeInfo i : Natives.asList(l)) {
        if (i.currentRevision() != null && i.revisions().containsKey(i.currentRevision())) {
          RevisionInfo currentRevision = i.revision(i.currentRevision());
          ChangeAndCommit c = ChangeAndCommit.create();
          c.setId(i.id());
          c.setCommit(currentRevision.commit());
          c.setChangeNumber(i.legacyId().get());
          c.setRevisionNumber(currentRevision._number());
          c.setBranch(i.branch());
          c.setProject(i.project());
          c.setSubmittable(i.submittable() && i.mergeable());
          c.setStatus(i.status().asChangeStatus().toString());
          arr.push(c);
        }
      }
      return arr;
    }
  }

  public static class RelatedInfo extends JavaScriptObject {
    public final native JsArray<ChangeAndCommit> changes() /*-{ return this.changes }-*/;
    protected RelatedInfo() {
    }
  }

  public static class ChangeAndCommit extends JavaScriptObject {
    static ChangeAndCommit create() {
      return (ChangeAndCommit) createObject();
    }

    public final native String id() /*-{ return this.change_id }-*/;
    public final native CommitInfo commit() /*-{ return this.commit }-*/;
    final native String branch() /*-{ return this.branch }-*/;
    final native String project() /*-{ return this.project }-*/;
    final native boolean submittable() /*-{ return this._submittable ? true : false; }-*/;
    final Change.Status status() {
      String s = statusRaw();
      return s != null ? Change.Status.valueOf(s) : null;
    }
    private native String statusRaw() /*-{ return this.status; }-*/;

    final native void setId(String i)
    /*-{ if(i)this.change_id=i; }-*/;

    final native void setCommit(CommitInfo c)
    /*-{ if(c)this.commit=c; }-*/;

    final native void setBranch(String b)
    /*-{ if(b)this.branch=b; }-*/;

    final native void setProject(String b)
    /*-{ if(b)this.project=b; }-*/;

    public final Change.Id legacyId() {
      return hasChangeNumber() ? new Change.Id(_changeNumber()) : null;
    }

    public final PatchSet.Id patchSetId() {
      return hasChangeNumber() && hasRevisionNumber()
          ? new PatchSet.Id(legacyId(), _revisionNumber())
          : null;
    }

    public final native boolean hasChangeNumber()
    /*-{ return this.hasOwnProperty('_change_number') }-*/;

    final native boolean hasRevisionNumber()
    /*-{ return this.hasOwnProperty('_revision_number') }-*/;

    final native boolean hasCurrentRevisionNumber()
    /*-{ return this.hasOwnProperty('_current_revision_number') }-*/;

    final native int _changeNumber()
    /*-{ return this._change_number }-*/;

    final native int _revisionNumber()
    /*-{ return this._revision_number }-*/;

    final native int _currentRevisionNumber()
    /*-{ return this._current_revision_number }-*/;

    final native void setChangeNumber(int n)
    /*-{ this._change_number=n; }-*/;

    final native void setRevisionNumber(int n)
    /*-{ this._revision_number=n; }-*/;

    final native void setCurrentRevisionNumber(int n)
    /*-{ this._current_revision_number=n; }-*/;

    final native void setSubmittable(boolean s)
    /*-{ this._submittable=s; }-*/;

    final native void setStatus(String s)
    /*-{ if(s)this.status=s; }-*/;

    protected ChangeAndCommit() {
    }
  }
}
