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

import com.google.gerrit.client.auth.openid.OpenIdSignInDialog;
import com.google.gerrit.client.auth.userpass.UserPassSignInDialog;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.LinkMenuBar;
import com.google.gerrit.client.ui.LinkMenuItem;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.common.ClientVersion;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.auth.SignInMode;
import com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.common.data.HostPageData;
import com.google.gerrit.common.data.SystemInfoService;
import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.AccountGeneralPreferences;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.http.client.URL;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.ui.Accessibility;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TabPanel;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwtexpui.clippy.client.CopyableLabel;
import com.google.gwtexpui.user.client.UserAgent;
import com.google.gwtexpui.user.client.ViewSite;
import com.google.gwtjsonrpc.client.JsonDefTarget;
import com.google.gwtjsonrpc.client.JsonUtil;
import com.google.gwtjsonrpc.client.XsrfManager;
import com.google.gwtorm.client.KeyUtil;

import java.util.ArrayList;

public class Gerrit implements EntryPoint {
  public static final GerritConstants C = GWT.create(GerritConstants.class);
  public static final GerritMessages M = GWT.create(GerritMessages.class);
  public static final GerritResources RESOURCES =
      GWT.create(GerritResources.class);
  public static final SystemInfoService SYSTEM_SVC;

  private static String myHost;
  private static GerritConfig myConfig;
  private static Account myAccount;

  private static TabPanel menuLeft;
  private static LinkMenuBar menuRight;
  private static RootPanel siteHeader;
  private static RootPanel siteFooter;
  private static SearchPanel searchPanel;
  private static final Dispatcher dispatcher = new Dispatcher();
  private static ViewSite<Screen> body;

  static {
    SYSTEM_SVC = GWT.create(SystemInfoService.class);
    JsonUtil.bind(SYSTEM_SVC, "rpc/SystemInfoService");
  }

  /**
   * Load the screen at the given location, displaying when ready.
   * <p>
   * If the URL is not already pointing at this location, a new item will be
   * added to the browser's history when the screen is fully loaded and
   * displayed on the UI.
   *
   * @param token location to parse, load, and render.
   */
  public static void display(final String token) {
    if (body.getView() == null || !body.getView().displayToken(token)) {
      dispatcher.display(token);
    }
  }

  /**
   * Load the screen passed, assuming token can be used to locate it.
   * <p>
   * The screen is loaded in the background. When it is ready to be visible a
   * new item will be added to the browser's history, the screen will be made
   * visible, and the window title may be updated.
   * <p>
   * If {@link Screen#isRequiresSignIn()} is true and the user is not signed in
   * yet the screen instance will be discarded, sign-in will take place, and
   * will redirect to this location upon success.
   *
   * @param token location that refers to {@code view}.
   * @param view the view to load.
   */
  public static void display(final String token, final Screen view) {
    if (view.isRequiresSignIn() && !isSignedIn()) {
      doSignIn(token);
    } else {
      view.setToken(token);
      body.setView(view);
    }
  }

  /**
   * Update the current history token after a screen change.
   * <p>
   * The caller has already updated the UI, but wants to publish a different
   * history token for the current browser state. This really only makes sense
   * if the caller is a {@code TabPanel} and is firing an event when the tab
   * changed to a different part.
   *
   * @param token new location that is already visible.
   */
  public static void updateImpl(final String token) {
    History.newItem(token, false);

    if (historyHooks != null) {
      // Because we blocked firing the event our history hooks won't be
      // informed of the current token. Manually fire the event to them.
      //
      dispatchHistoryHooks(token);
    }
  }

  public static void setQueryString(String query) {
    searchPanel.setText(query);
  }

  public static void setWindowTitle(final Screen screen, final String text) {
    if (screen == body.getView()) {
      if (text == null || text.length() == 0) {
        Window.setTitle(M.windowTitle1(myHost));
      } else {
        Window.setTitle(M.windowTitle2(text, myHost));
      }
    }
  }

  /** Get the public configuration data used by this Gerrit instance. */
  public static GerritConfig getConfig() {
    return myConfig;
  }

  /** @return the currently signed in user's account data; null if no account */
  public static Account getUserAccount() {
    return myAccount;
  }

  /** @return true if the user is currently authenticated */
  public static boolean isSignedIn() {
    return getUserAccount() != null;
  }

  /** Sign the user into the application. */
  public static void doSignIn(final String token) {
    switch (myConfig.getAuthType()) {
      case HTTP:
      case HTTP_LDAP:
        Location.assign(Location.getPath() + "login/" + token);
        break;

      case DEVELOPMENT_BECOME_ANY_ACCOUNT:
        Location.assign(Location.getPath() + "become");
        break;

      case OPENID:
        new OpenIdSignInDialog(SignInMode.SIGN_IN, token, null).center();
        break;

      case LDAP:
        new UserPassSignInDialog(token, null).center();
        break;
    }
  }

  public void onModuleLoad() {
    UserAgent.assertNotInIFrame();

    KeyUtil.setEncoderImpl(new KeyUtil.Encoder() {
      @Override
      public String encode(final String e) {
        return fixPathImpl(URL.encodeComponent(e));
      }

      @Override
      public String decode(final String e) {
        return URL.decodeComponent(e);
      }

      private native String fixPathImpl(String path)
      /*-{ return path.replace(/%2F/g, "/"); }-*/;
    });

    RESOURCES.gwt_override().ensureInjected();
    RESOURCES.css().ensureInjected();

    final RootPanel gTopMenu = RootPanel.get("gerrit_topmenu");
    final RootPanel gStarting = RootPanel.get("gerrit_startinggerrit");
    final RootPanel gBody = RootPanel.get("gerrit_body");
    final RootPanel gBottomMenu = RootPanel.get("gerrit_btmmenu");

    gTopMenu.setStyleName(RESOURCES.css().gerritTopMenu());
    gBody.setStyleName(RESOURCES.css().gerritBody());

    initHostname();
    Window.setTitle(M.windowTitle1(myHost));
    initHistoryHooks();
    populateBottomMenu(gBottomMenu);

    final Grid menuLine = new Grid(1, 3);
    menuLeft = new TabPanel();
    menuRight = new LinkMenuBar();
    searchPanel = new SearchPanel();
    menuLeft.setStyleName(RESOURCES.css().topmenuMenuLeft());
    menuLine.setStyleName(RESOURCES.css().topmenu());
    gTopMenu.add(menuLine);
    final FlowPanel menuRightPanel = new FlowPanel();
    menuRightPanel.setStyleName(RESOURCES.css().topmenuMenuRight());
    menuRightPanel.add(menuRight);
    menuRightPanel.add(searchPanel);
    menuLine.setWidget(0, 0, menuLeft);
    menuLine.setWidget(0, 1, new FlowPanel());
    menuLine.setWidget(0, 2, menuRightPanel);
    final CellFormatter fmt = menuLine.getCellFormatter();
    fmt.setStyleName(0, 0, RESOURCES.css().topmenuTDmenu());
    fmt.setStyleName(0, 1, RESOURCES.css().topmenuTDglue());
    fmt.setStyleName(0, 2, RESOURCES.css().topmenuTDmenu());

    siteHeader = RootPanel.get("gerrit_header");
    siteFooter = RootPanel.get("gerrit_footer");

    body = new ViewSite<Screen>() {
      @Override
      protected void onShowView(Screen view) {
        final String token = view.getToken();
        if (!token.equals(History.getToken())) {
          History.newItem(token, false);
          if (historyHooks != null) {
            dispatchHistoryHooks(token);
          }
        }
        super.onShowView(view);
        view.onShowView();
      }
    };
    gBody.add(body);

    final RpcStatus rpcStatus = new RpcStatus(gTopMenu);
    JsonUtil.addRpcStartHandler(rpcStatus);
    JsonUtil.addRpcCompleteHandler(rpcStatus);
    JsonUtil.setDefaultXsrfManager(new XsrfManager() {
      @Override
      public String getToken(JsonDefTarget proxy) {
        return Cookies.getCookie("GerritAccount");
      }

      @Override
      public void setToken(JsonDefTarget proxy, String token) {
        // Ignore the request, we always rely upon the cookie.
      }
    });

    final HostPageDataService hpd = GWT.create(HostPageDataService.class);
    hpd.load(new GerritCallback<HostPageData>() {
      public void onSuccess(final HostPageData result) {
        myConfig = result.config;
        if (result.account != null) {
          myAccount = result.account;
          applyUserPreferences();
        }
        onModuleLoad2(gStarting);
      }
    });
  }

  private static void initHostname() {
    myHost = Location.getHostName();
    final int d1 = myHost.indexOf('.');
    if (d1 < 0) {
      return;
    }
    final int d2 = myHost.indexOf('.', d1 + 1);
    if (d2 >= 0) {
      myHost = myHost.substring(0, d2);
    }
  }

  private static ArrayList<JavaScriptObject> historyHooks;

  private static native void initHistoryHooks()
  /*-{ $wnd['gerrit_addHistoryHook'] = function(h) { @com.google.gerrit.client.Gerrit::addHistoryHook(Lcom/google/gwt/core/client/JavaScriptObject;)(h); }; }-*/;

  static void addHistoryHook(final JavaScriptObject hook) {
    if (historyHooks == null) {
      historyHooks = new ArrayList<JavaScriptObject>();
      History.addValueChangeHandler(new ValueChangeHandler<String>() {
        @Override
        public void onValueChange(ValueChangeEvent<String> event) {
          dispatchHistoryHooks(event.getValue());
        }
      });
    }
    historyHooks.add(hook);
  }

  private static native void callHistoryHook(JavaScriptObject hook, String url)
  /*-{ hook(url); }-*/;

  private static void dispatchHistoryHooks(final String historyToken) {
    final String url = Location.getPath() + "#" + historyToken;
    for (final JavaScriptObject hook : historyHooks) {
      callHistoryHook(hook, url);
    }
  }

  private static void populateBottomMenu(final RootPanel btmmenu) {
    final Label keyHelp = new Label(C.keyHelp());
    keyHelp.setStyleName(RESOURCES.css().keyhelp());
    btmmenu.add(keyHelp);

    String vs;
    if (GWT.isScript()) {
      final ClientVersion v = GWT.create(ClientVersion.class);
      vs = v.version().getText();
      if (vs.startsWith("v")) {
        vs = vs.substring(1);
      }
    } else {
      vs = "dev";
    }

    final HTML version = new HTML(M.poweredBy(vs));
    version.setStyleName(RESOURCES.css().version());
    btmmenu.add(version);
  }

  private void onModuleLoad2(final RootPanel starting) {
    refreshMenuBar();

    starting.getElement().getParentElement().removeChild(starting.getElement());
    RootPanel.detachNow(starting);

    History.addValueChangeHandler(new ValueChangeHandler<String>() {
      public void onValueChange(final ValueChangeEvent<String> event) {
        display(event.getValue());
      }
    });
    JumpKeys.register(body);

    if ("".equals(History.getToken())) {
      if (isSignedIn()) {
        display(PageLinks.MINE);
      } else {
        display(PageLinks.ALL_OPEN);
      }
    } else {
      display(History.getToken());
    }
  }

  public static void refreshMenuBar() {
    menuLeft.clear();
    menuRight.clear();

    final boolean signedIn = isSignedIn();
    final GerritConfig cfg = getConfig();
    LinkMenuBar m;

    m = new LinkMenuBar();
    addLink(m, C.menuAllOpen(), PageLinks.ALL_OPEN);
    addLink(m, C.menuAllMerged(), PageLinks.ALL_MERGED);
    addLink(m, C.menuAllAbandoned(), PageLinks.ALL_ABANDONED);
    menuLeft.add(m, C.menuAll());

    if (signedIn) {
      m = new LinkMenuBar();
      addLink(m, C.menuMyChanges(), PageLinks.MINE);
      addLink(m, C.menyMyDrafts(), PageLinks.MINE_DRAFTS);
      addLink(m, C.menuMyStarredChanges(), PageLinks.MINE_STARRED);
      menuLeft.add(m, C.menuMine());
      menuLeft.selectTab(1);
    } else {
      menuLeft.selectTab(0);
    }

    if (signedIn) {
      m = new LinkMenuBar();
      addLink(m, C.menuGroups(), PageLinks.ADMIN_GROUPS);
      addLink(m, C.menuProjects(), PageLinks.ADMIN_PROJECTS);
      menuLeft.add(m, C.menuAdmin());
    }

    if (signedIn) {
      whoAmI();
      addLink(menuRight, C.menuSettings(), PageLinks.SETTINGS);
      menuRight.add(anchor(C.menuSignOut(), "logout"));
    } else {
      switch (cfg.getAuthType()) {
        case HTTP:
        case HTTP_LDAP:
          break;

        case OPENID:
          menuRight.addItem(C.menuRegister(), new Command() {
            public void execute() {
              final String to = History.getToken();
              new OpenIdSignInDialog(SignInMode.REGISTER, to, null).center();
            }
          });
          menuRight.addItem(C.menuSignIn(), new Command() {
            public void execute() {
              doSignIn(History.getToken());
            }
          });
          break;

        case LDAP:
          if (cfg.getRegisterUrl() != null) {
            menuRight.add(anchor(C.menuRegister(), cfg.getRegisterUrl()));
          }
          menuRight.addItem(C.menuSignIn(), new Command() {
            public void execute() {
              doSignIn(History.getToken());
            }
          });
          break;

        case DEVELOPMENT_BECOME_ANY_ACCOUNT:
          menuRight.add(anchor("Become", "become"));
          break;
      }
    }
  }

  public static void applyUserPreferences() {
    final AccountGeneralPreferences p = myAccount.getGeneralPreferences();
    CopyableLabel.setFlashEnabled(p.isUseFlashClipboard());
    if (siteHeader != null) {
      siteHeader.setVisible(p.isShowSiteHeader());
    }
    if (siteFooter != null) {
      siteFooter.setVisible(p.isShowSiteHeader());
    }
  }

  private static void whoAmI() {
    final String name = FormatUtil.nameEmail(getUserAccount());
    final InlineLabel l = new InlineLabel(name);
    l.setStyleName(RESOURCES.css().menuBarUserName());
    menuRight.add(l);
  }

  private static Anchor anchor(final String text, final String to) {
    final Anchor a = new Anchor(text, to);
    a.setStyleName(RESOURCES.css().menuItem());
    Accessibility.setRole(a.getElement(), Accessibility.ROLE_MENUITEM);
    return a;
  }

  private static void addLink(final LinkMenuBar m, final String text,
      final String historyToken) {
    m.addItem(new LinkMenuItem(text, historyToken));
  }
}
