// Copyright (C) 2015 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.googlesource.gerrit.plugins.xdocs.client;

import com.google.gerrit.plugin.client.Plugin;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.ImageResourceRenderer;
import com.google.gwt.user.client.ui.InlineHyperlink;
import com.google.gwt.user.client.ui.Label;

import com.googlesource.gerrit.plugins.xdocs.client.ChangeInfo.RevisionInfo;

public class PatchSetSelectBox extends FlowPanel {

  public enum DisplaySide {
    A, B
  }

  public static enum DiffView {
    SIDE_BY_SIDE,
    UNIFIED_DIFF
  }

  private final DiffView diffView;
  private final DisplaySide side;
  private final ChangeInfo change;
  private final Integer basePatchSet;
  private final int patchSet;
  private final String path;

  public PatchSetSelectBox(DiffView diffView, DisplaySide side,
      ChangeInfo change, Integer basePatchSet, int patchSet, String path) {
    this.diffView = diffView;
    this.side = side;
    this.change = change;
    this.path = path;
    this.basePatchSet = basePatchSet;
    this.patchSet = patchSet;

    init();
  }

  private void init() {
    setStyleName("xdocs-patch-set-select-box");
    if (isSideBySideDiff()) {
      addStyleName("xdocs-patch-set-select-box-side-by-side");
    }

    addPatchSetLabel();

    if (sideA()) {
      add(createBaseLink());
    } else if (isUnifiedDiff()) {
      // create hidden 'Base' link to align the patch set links with side A
      add(createHiddenBaseLink());
    }

    JsArray<RevisionInfo> list = change.revisions().values();
    RevisionInfo.sortRevisionInfoByNumber(list);
    for (int i = 0; i < list.length(); i++) {
      add(createLink(list.get(i)));
    }

    if (!FileInfo.COMMIT_MSG.equals(path)) {
      add(createDownloadLink());
    }

    if (showEditIcon()) {
      add(createEditIcon());
    }
  }

  private void addPatchSetLabel() {
    add(new Label("Patch Set"));
    if (isUnifiedDiff()) {
      Label l = new Label(sideA() ? "(-)" : "(+)");
      l.addStyleName("xdocs-monospace");
      add(l);
    }
  }

  private boolean isSideBySideDiff() {
    return diffView == DiffView.SIDE_BY_SIDE;
  }

  private boolean isUnifiedDiff() {
    return diffView == DiffView.UNIFIED_DIFF;
  }

  private boolean sideA() {
    return side == DisplaySide.A;
  }

  private InlineHyperlink createBaseLink() {
    InlineHyperlink link = new InlineHyperlink("Base",
        getUrl(change._number(), null, patchSet, path, diffView));
    if (isBaseSelected()) {
      link.setStyleName("xdocs-patch-set-select-box-selected");
    }
    return link;
  }

  private InlineHyperlink createHiddenBaseLink() {
    InlineHyperlink link = new InlineHyperlink("Base", null);
    link.addStyleName("xdocs-hidden");
    return link;
  }

  private InlineHyperlink createLink(RevisionInfo r) {
    String label = r.is_edit() ? "edit" : Integer.toString(r._number());
    Integer patchSetIdA = sideA() ? Integer.valueOf(r._number()) : basePatchSet;
    int patchSetIdB = sideA() ? patchSet : r._number();
    InlineHyperlink link = new InlineHyperlink(label,
        getUrl(change._number(), patchSetIdA, patchSetIdB, path, diffView));
    if (isSelected(r._number())) {
      link.setStyleName("xdocs-patch-set-select-box-selected");
    }
    return link;
  }

  private Anchor createDownloadLink() {
    String base = GWT.getHostPageBaseURL() + "cat/";
    String sideUrl = isBaseSelected() ? "1" : "0";
    int ps = isBaseSelected()
        ? change.revision(change.current_revision())._number()
        : getSelectedPatchSet();
    Anchor anchor = new Anchor(
        new ImageResourceRenderer().render(XDocsPlugin.RESOURCES.downloadIcon()),
        base + URL.encode(change._number() + "," + ps + "," + path) + "^" + sideUrl);
    anchor.setTitle("Download");
    return anchor;
  }

  private boolean showEditIcon() {
    if (sideA() || !change.isOpen() || !Plugin.get().isSignedIn()) {
      return false;
    }

    if (change.has_edit()) {
      return patchSet == 0;
    } else {
      return patchSet == change.revision(change.current_revision())._number();
    }
  }

  private Anchor createEditIcon() {
    Anchor anchor = new Anchor(
        new ImageResourceRenderer().render(XDocsPlugin.RESOURCES.edit()),
        "#" + getEditUrl(change._number(), patchSet, path));
    anchor.setTitle("Edit");
    return anchor;
  }

  private Integer getSelectedPatchSet() {
    return sideA() ? basePatchSet : Integer.valueOf(patchSet);
  }

  private boolean isBaseSelected() {
    return getSelectedPatchSet() == null;
  }

  private boolean isSelected(int ps) {
    return getSelectedPatchSet() != null
        && getSelectedPatchSet().intValue() == ps;
  }

  private static String getUrl(int changeId, Integer patchSetIdA,
      int patchSetIdB, String path, DiffView diffView) {
    StringBuilder url = new StringBuilder();
    url.append("/x/");
    url.append(Plugin.get().getName());
    url.append("/c/");
    url.append(changeId);
    url.append("/");
    if (patchSetIdA != null) {
      url.append(patchSetIdA);
      url.append("..");
    }
    url.append(patchSetIdB);
    url.append("/");
    url.append(path);
    if (diffView == DiffView.UNIFIED_DIFF) {
      url.append(",unified");
    }
    return url.toString();
  }

  private static String getEditUrl(int changeId, int patchSetId, String path) {
    StringBuilder url = new StringBuilder();
    url.append("/c/");
    url.append(changeId);
    url.append("/");
    url.append(patchSetId);
    url.append("/");
    url.append(path);
    url.append(",edit");
    return url.toString();
  }
}
