// 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.diff;

import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.ReviewInfo;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.diff.DiffInfo.Region;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.info.FileInfo;
import com.google.gerrit.client.info.GitwebInfo;
import com.google.gerrit.client.info.WebLinkInfo;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.rpc.RestApi;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsArrayString;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
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.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.CheckBox;
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.Image;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;

import java.util.List;

public class Header extends Composite {
  interface Binder extends UiBinder<HTMLPanel, Header> {}
  private static final Binder uiBinder = GWT.create(Binder.class);
  static {
    Resources.I.style().ensureInjected();
  }

  private static enum ReviewedState {
    AUTO_REVIEW, LOADED
  }

  @UiField CheckBox reviewed;
  @UiField Element project;
  @UiField Element filePath;

  @UiField Element noDiff;
  @UiField FlowPanel linkPanel;

  @UiField InlineHyperlink prev;
  @UiField InlineHyperlink up;
  @UiField InlineHyperlink next;
  @UiField Image preferences;

  private final KeyCommandSet keys;
  private final PatchSet.Id base;
  private final PatchSet.Id patchSetId;
  private final String path;
  private boolean hasPrev;
  private boolean hasNext;
  private String nextPath;
  private PreferencesAction prefsAction;
  private ReviewedState reviewedState;

  Header(KeyCommandSet keys, PatchSet.Id base, PatchSet.Id patchSetId,
      String path) {
    initWidget(uiBinder.createAndBindUi(this));
    this.keys = keys;
    this.base = base;
    this.patchSetId = patchSetId;
    this.path = path;

    if (!Gerrit.isSignedIn()) {
      reviewed.getElement().getStyle().setVisibility(Visibility.HIDDEN);
    }
    SafeHtml.setInnerHTML(filePath, formatPath(path, null, null));
    up.setTargetHistoryToken(PageLinks.toChange(
        patchSetId.getParentKey(),
        base != null ? base.getId() : null, patchSetId.getId()));
  }

  public static SafeHtml formatPath(String path, String project, String commit) {
    SafeHtmlBuilder b = new SafeHtmlBuilder();
    if (Patch.COMMIT_MSG.equals(path)) {
      return b.append(Util.C.commitMessage());
    }

    GitwebInfo gw = (project != null && commit != null)
        ? Gerrit.info().gitweb() : null;
    int s = path.lastIndexOf('/') + 1;
    if (gw != null && s > 0) {
      String base = path.substring(0, s - 1);
      b.openAnchor()
          .setAttribute("href", gw.toFile(project, commit, base))
          .setAttribute("title", gw.getLinkName())
          .append(base)
          .closeAnchor()
          .append('/');
    } else {
      b.append(path.substring(0, s));
    }
    b.openElement("b");
    b.append(path.substring(s));
    b.closeElement("b");
    return b;
  }

  @Override
  protected void onLoad() {
    DiffApi.list(patchSetId, base, new GerritCallback<NativeMap<FileInfo>>() {
      @Override
      public void onSuccess(NativeMap<FileInfo> result) {
        JsArray<FileInfo> files = result.values();
        FileInfo.sortFileInfoByPath(files);
        int index = 0; // TODO: Maybe use patchIndex.
        for (int i = 0; i < files.length(); i++) {
          if (path.equals(files.get(i).path())) {
            index = i;
            break;
          }
        }
        FileInfo nextInfo = index == files.length() - 1
            ? null
            : files.get(index + 1);
        KeyCommand p = setupNav(prev, '[', PatchUtil.C.previousFileHelp(),
            index == 0 ? null : files.get(index - 1));
        KeyCommand n = setupNav(next, ']', PatchUtil.C.nextFileHelp(),
            nextInfo);
        if (p != null && n != null) {
          keys.pair(p, n);
        }
        nextPath = nextInfo != null ? nextInfo.path() : null;
      }
    });

    if (Gerrit.isSignedIn()) {
      ChangeApi.revision(patchSetId).view("files")
        .addParameterTrue("reviewed")
        .get(new AsyncCallback<JsArrayString>() {
            @Override
            public void onSuccess(JsArrayString result) {
              boolean b = Natives.asList(result).contains(path);
              reviewed.setValue(b, false);
              if (!b && reviewedState == ReviewedState.AUTO_REVIEW) {
                postAutoReviewed();
              }
              reviewedState = ReviewedState.LOADED;
            }

            @Override
            public void onFailure(Throwable caught) {
            }
          });
    }
  }

  void autoReview() {
    if (reviewedState == ReviewedState.LOADED && !reviewed.getValue()) {
      postAutoReviewed();
    } else {
      reviewedState = ReviewedState.AUTO_REVIEW;
    }
  }

  void setChangeInfo(ChangeInfo info) {
    GitwebInfo gw = Gerrit.info().gitweb();
    if (gw != null) {
      for (RevisionInfo rev : Natives.asList(info.revisions().values())) {
        if (patchSetId.getId().equals(rev.id())) {
          String c = rev.name();
          SafeHtml.setInnerHTML(filePath, formatPath(path, info.project(), c));
          SafeHtml.setInnerHTML(project, new SafeHtmlBuilder()
              .openAnchor()
              .setAttribute("href", gw.toFile(info.project(), c, ""))
              .setAttribute("title", gw.getLinkName())
              .append(info.project())
              .closeAnchor());
          return;
        }
      }
    }

    project.setInnerText(info.project());
  }

  void init(PreferencesAction pa, List<InlineHyperlink> links,
      List<WebLinkInfo> webLinks) {
    prefsAction = pa;
    prefsAction.setPartner(preferences);

    for (InlineHyperlink link : links) {
      linkPanel.add(link);
    }
    for (WebLinkInfo webLink : webLinks) {
      linkPanel.add(webLink.toAnchor());
    }
  }

  @UiHandler("reviewed")
  void onValueChange(ValueChangeEvent<Boolean> event) {
    if (event.getValue()) {
      reviewed().put(CallbackGroup.<ReviewInfo> emptyCallback());
    } else {
      reviewed().delete(CallbackGroup.<ReviewInfo> emptyCallback());
    }
  }

  private void postAutoReviewed() {
    reviewed().background().put(new AsyncCallback<ReviewInfo>() {
        @Override
        public void onSuccess(ReviewInfo result) {
          reviewed.setValue(true, false);
        }

        @Override
        public void onFailure(Throwable caught) {
        }
      });
  }

  private RestApi reviewed() {
    return ChangeApi.revision(patchSetId)
        .view("files")
        .id(path)
        .view("reviewed");
  }

  @UiHandler("preferences")
  void onPreferences(@SuppressWarnings("unused") ClickEvent e) {
    prefsAction.show();
  }

  private String url(FileInfo info) {
    return info.binary()
      ? Dispatcher.toUnified(base, patchSetId, info.path())
      : Dispatcher.toSideBySide(base, patchSetId, info.path());
  }

  private KeyCommand setupNav(InlineHyperlink link, char key, String help, FileInfo info) {
    if (info != null) {
      final String url = url(info);
      link.setTargetHistoryToken(url);
      link.setTitle(PatchUtil.M.fileNameWithShortcutKey(
          FileInfo.getFileName(info.path()),
          Character.toString(key)));
      KeyCommand k = new KeyCommand(0, key, help) {
        @Override
        public void onKeyPress(KeyPressEvent event) {
          Gerrit.display(url);
        }
      };
      keys.add(k);
      if (link == prev) {
        hasPrev = true;
      } else {
        hasNext = true;
      }
      return k;
    } else {
      link.getElement().getStyle().setVisibility(Visibility.HIDDEN);
      keys.add(new UpToChangeCommand(patchSetId, 0, key));
      return null;
    }
  }

  Runnable toggleReviewed() {
    return new Runnable() {
      @Override
      public void run() {
        reviewed.setValue(!reviewed.getValue(), true);
      }
    };
  }

  Runnable navigate(Direction dir) {
    switch (dir) {
      case PREV:
        return new Runnable() {
          @Override
          public void run() {
            (hasPrev ? prev : up).go();
          }
        };
      case NEXT:
        return new Runnable() {
          @Override
          public void run() {
            (hasNext ? next : up).go();
          }
        };
      default:
        return new Runnable() {
          @Override
          public void run() {
          }
        };
    }
  }

  Runnable reviewedAndNext() {
    return new Runnable() {
      @Override
      public void run() {
        if (Gerrit.isSignedIn()) {
          reviewed.setValue(true, true);
        }
        navigate(Direction.NEXT).run();
      }
    };
  }

  String getNextPath() {
    return nextPath;
  }

  void setNoDiff(DiffInfo diff) {
    JsArray<Region> regions = diff.content();
    boolean b = regions.length() == 0
        || (regions.length() == 1 && regions.get(0).ab() != null);
    UIObject.setVisible(noDiff, b);
  }
}
