// 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 static com.google.gerrit.common.data.GlobalCapability.CREATE_GROUP;
import static com.google.gerrit.common.data.GlobalCapability.CREATE_PROJECT;
import static com.google.gerrit.common.data.GlobalCapability.VIEW_PLUGINS;
import static com.google.gerrit.common.data.HostPageData.XSRF_COOKIE_NAME;

import com.google.gerrit.client.account.AccountApi;
import com.google.gerrit.client.account.AccountCapabilities;
import com.google.gerrit.client.account.EditPreferences;
import com.google.gerrit.client.admin.ProjectScreen;
import com.google.gerrit.client.api.ApiGlue;
import com.google.gerrit.client.api.PluginLoader;
import com.google.gerrit.client.change.LocalComments;
import com.google.gerrit.client.changes.ChangeListScreen;
import com.google.gerrit.client.config.ConfigServerApi;
import com.google.gerrit.client.documentation.DocInfo;
import com.google.gerrit.client.info.AccountInfo;
import com.google.gerrit.client.info.AuthInfo;
import com.google.gerrit.client.info.GeneralPreferences;
import com.google.gerrit.client.info.ServerInfo;
import com.google.gerrit.client.info.TopMenu;
import com.google.gerrit.client.info.TopMenuItem;
import com.google.gerrit.client.info.TopMenuList;
import com.google.gerrit.client.rpc.CallbackGroup;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.LinkMenuBar;
import com.google.gerrit.client.ui.LinkMenuItem;
import com.google.gerrit.client.ui.MorphingTabPanel;
import com.google.gerrit.client.ui.ProjectLinkMenuItem;
import com.google.gerrit.client.ui.Screen;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.data.HostPageData;
import com.google.gerrit.common.data.SystemInfoService;
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
import com.google.gerrit.extensions.client.EditPreferencesInfo;
import com.google.gerrit.extensions.client.GerritTopMenu;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.http.client.Request;
import com.google.gwt.http.client.RequestBuilder;
import com.google.gwt.http.client.RequestCallback;
import com.google.gwt.http.client.RequestException;
import com.google.gwt.http.client.Response;
import com.google.gwt.http.client.URL;
import com.google.gwt.http.client.UrlBuilder;
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.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.RootPanel;
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.HashMap;
import java.util.List;
import java.util.Map;

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;
  public static final EventBus EVENT_BUS = GWT.create(SimpleEventBus.class);
  public static final Themer THEMER = GWT.create(Themer.class);
  public static final String PROJECT_NAME_MENU_VAR = "${projectName}";
  public static final String INDEX = "Documentation/index.html";

  private static String myHost;
  private static ServerInfo myServerInfo;
  private static AccountInfo myAccount;
  private static GeneralPreferences myPrefs;
  private static UrlAliasMatcher urlAliasMatcher;
  private static boolean hasDocumentation;
  private static boolean docSearch;
  private static String docUrl;
  private static HostPageData.Theme myTheme;
  private static String defaultScreenToken;
  private static DiffPreferencesInfo myAccountDiffPref;
  private static EditPreferencesInfo editPrefs;
  private static String xGerritAuth;
  private static boolean isNoteDbEnabled;

  private static Map<String, LinkMenuBar> menuBars;

  private static MorphingTabPanel menuLeft;
  private static LinkMenuBar menuRight;
  private static RootPanel topMenu;
  private static RootPanel siteHeader;
  private static RootPanel siteFooter;
  private static RootPanel bottomMenu;
  private static SearchPanel searchPanel;
  private static final Dispatcher dispatcher = new Dispatcher();
  private static ViewSite<Screen> body;
  private static String lastChangeListToken;
  private static String lastViewToken;

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

  static void upgradeUI(String token) {
    History.newItem(Dispatcher.RELOAD_UI + token, false);
    Window.Location.reload();
  }

  public static void displayLastChangeList() {
    if (lastChangeListToken != null) {
      display(lastChangeListToken);
    } else if (isSignedIn()) {
      display(PageLinks.MINE);
    } else {
      display(PageLinks.toChangeQuery("status:open"));
    }
  }

  public static String getPriorView() {
    return lastViewToken;
  }

  /**
   * 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);
      if (isSignedIn()) {
        LocalComments.saveInlineComments();
      }
      body.setView(view);
    }
  }

  public static void selectMenu(LinkMenuBar bar) {
    menuLeft.selectTab(menuLeft.getWidgetIndex(bar));
  }

  /**
   * 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);
    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));
      }
    }
  }

  public static int getHeaderFooterHeight() {
    int h = bottomMenu.getOffsetHeight();
    if (topMenu.isVisible()) {
      h += topMenu.getOffsetHeight();
    }
    if (siteHeader.isVisible()) {
      h += siteHeader.getOffsetHeight();
    }
    if (siteFooter.isVisible()) {
      h += siteFooter.getOffsetHeight();
    }
    return h;
  }

  public static void setHeaderVisible(boolean visible) {
    topMenu.setVisible(visible);
    siteHeader.setVisible(visible && getUserPreferences().showSiteHeader());
  }

  public static boolean isHeaderVisible() {
    return topMenu.isVisible();
  }

  public static String getDefaultScreenToken() {
    return defaultScreenToken;
  }

  public static RootPanel getBottomMenu() {
    return bottomMenu;
  }

  /** Get the public configuration data used by this Gerrit instance. */
  public static ServerInfo info() {
    return myServerInfo;
  }

  public static UrlAliasMatcher getUrlAliasMatcher() {
    return urlAliasMatcher;
  }

  /** Site theme information (site specific colors)/ */
  public static HostPageData.Theme getTheme() {
    return myTheme;
  }

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

  /** @return access token to prove user identity during REST API calls. */
  public static String getXGerritAuth() {
    return xGerritAuth;
  }

  /** @return the preferences of the currently signed in user, the default preferences if not signed in */
  public static GeneralPreferences getUserPreferences() {
    return myPrefs;
  }

  /** @return the currently signed in users's diff preferences, or default values */
  public static DiffPreferencesInfo getDiffPreferences() {
    return myAccountDiffPref;
  }

  public static void setDiffPreferences(DiffPreferencesInfo accountDiffPref) {
    myAccountDiffPref = accountDiffPref;
  }

  /** @return the edit preferences of the current user, null if not signed-in */
  public static EditPreferencesInfo getEditPreferences() {
    return editPrefs;
  }

  public static void setEditPreferences(EditPreferencesInfo p) {
    editPrefs = p;
  }

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

  /** Sign the user into the application. */
  public static void doSignIn(String token) {
    Location.assign(loginRedirect(token));
  }

  public static boolean isNoteDbEnabled() {
    return isNoteDbEnabled;
  }

  public static String loginRedirect(String token) {
    if (token == null) {
      token = "";
    } else if (token.startsWith("/")) {
      token = token.substring(1);
    }

    return selfRedirect("login/") + URL.encodePathSegment("#/" + token);
  }

  public static String selfRedirect(String suffix) {
    // Clean up the path. Users seem to like putting extra slashes into the URL
    // which can break redirections by misinterpreting at either client or server.
    String path = Location.getPath();
    if (path == null || path.isEmpty()) {
      path = "/";
    } else {
      while (path.startsWith("//")) {
        path = path.substring(1);
      }
      while (path.endsWith("//")) {
        path = path.substring(0, path.length() - 1);
      }
      if (!path.endsWith("/")) {
        path = path + "/";
      }
    }

    if (suffix != null) {
      while (suffix.startsWith("/")) {
        suffix = suffix.substring(1);
      }
      path += suffix;
    }

    UrlBuilder builder = new UrlBuilder();
    builder.setProtocol(Location.getProtocol());
    builder.setHost(Location.getHost());
    String port = Location.getPort();
    if (port != null && !port.isEmpty()) {
      builder.setPort(Integer.parseInt(port));
    }
    builder.setPath(path);
    return builder.buildString();
  }

  static void deleteSessionCookie() {
    myAccount = AccountInfo.create(0, null, null, null);
    myAccountDiffPref = null;
    editPrefs = null;
    myPrefs = GeneralPreferences.createDefault();
    urlAliasMatcher.clearUserAliases();
    xGerritAuth = null;
    refreshMenuBar();

    // If the cookie was HttpOnly, this request to delete it will
    // most likely not be successful.  We can try anyway though.
    //
    Cookies.removeCookie("GerritAccount");
  }

  private void setXsrfToken() {
    xGerritAuth = Cookies.getCookie(XSRF_COOKIE_NAME);
    JsonUtil.setDefaultXsrfManager(new XsrfManager() {
      @Override
      public String getToken(JsonDefTarget proxy) {
        return xGerritAuth;
      }

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

  @Override
  public void onModuleLoad() {
    if (!canLoadInIFrame()) {
      UserAgent.assertNotInIFrame();
    }
    setXsrfToken();

    KeyUtil.setEncoderImpl(new KeyUtil.Encoder() {
      @Override
      public String encode(String e) {
        e = URL.encodeQueryString(e);
        e = fixPathImpl(e);
        e = fixColonImpl(e);
        e = fixDoubleQuote(e);
        return e;
      }

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

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

      private native String fixColonImpl(String path)
      /*-{ return path.replace(/%3A/g, ":"); }-*/;

      private native String fixDoubleQuote(String path)
      /*-{ return path.replace(/%22/g, '"'); }-*/;
    });

    initHostname();
    Window.setTitle(M.windowTitle1(myHost));

    RpcStatus.INSTANCE = new RpcStatus();
    CallbackGroup cbg = new CallbackGroup();
    getDocIndex(cbg.add(new GerritCallback<DocInfo>() {
      @Override
      public void onSuccess(DocInfo indexInfo) {
        hasDocumentation = indexInfo != null;
        docUrl = selfRedirect("/Documentation/");
      }
    }));
    ConfigServerApi.serverInfo(cbg.add(new GerritCallback<ServerInfo>() {
      @Override
      public void onSuccess(ServerInfo info) {
        myServerInfo = info;
        urlAliasMatcher = new UrlAliasMatcher(info.urlAliases());
        String du = info.gerrit().docUrl();
        if (du != null && !du.isEmpty()) {
          hasDocumentation = true;
          docUrl = du;
        }
        docSearch = info.gerrit().docSearch();
      }
    }));
    HostPageDataService hpd = GWT.create(HostPageDataService.class);
    hpd.load(cbg.addFinal(new GerritCallback<HostPageData>() {
      @Override
      public void onSuccess(final HostPageData result) {
        Document.get().getElementById("gerrit_hostpagedata").removeFromParent();
        myTheme = result.theme;
        isNoteDbEnabled = result.isNoteDbEnabled;
        if (result.accountDiffPref != null) {
          myAccountDiffPref = result.accountDiffPref;
        }
        if (result.accountDiffPref != null) {
          // TODO: Support options on the GetDetail REST endpoint so that it can
          // also return the preferences. Then we can fetch everything with a
          // single request and we don't need the callback group anymore.
          CallbackGroup cbg = new CallbackGroup();
          AccountApi.self().view("detail")
              .get(cbg.add(new GerritCallback<AccountInfo>() {
                @Override
                public void onSuccess(AccountInfo result) {
                  myAccount = result;
                }
          }));
          AccountApi.self().view("preferences")
              .get(cbg.add(new GerritCallback<GeneralPreferences>() {
            @Override
            public void onSuccess(GeneralPreferences prefs) {
              myPrefs = prefs;
              onModuleLoad2(result);
            }
          }));
          AccountApi.getEditPreferences(
              cbg.addFinal(new GerritCallback<EditPreferences>() {
            @Override
            public void onSuccess(EditPreferences prefs) {
              EditPreferencesInfo prefsInfo = new EditPreferencesInfo();
              prefs.copyTo(prefsInfo);
              editPrefs = prefsInfo;
            }
          }));
        } else {
          myAccount = AccountInfo.create(0, null, null, null);
          myPrefs = GeneralPreferences.createDefault();
          editPrefs = null;
          onModuleLoad2(result);
        }
      }
    }));
  }

  private native boolean canLoadInIFrame() /*-{
    return $wnd.gerrit_hostpagedata.canLoadInIFrame || false;
  }-*/;

  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 void dispatchHistoryHooks(String token) {
    ApiGlue.fireEvent("history", token);
  }

  private static void populateBottomMenu(RootPanel btmmenu, HostPageData hpd) {
    String vs = hpd.version;
    if (vs == null || vs.isEmpty()) {
      vs = "dev";
    }

    btmmenu.add(new InlineHTML(M.poweredBy(vs)));

    String reportBugUrl = info().gerrit().reportBugUrl();
    if (reportBugUrl != null) {
      String reportBugText = info().gerrit().reportBugText();
      Anchor a = new Anchor(
          reportBugText == null ? C.reportBug() : reportBugText,
          reportBugUrl);
      a.setTarget("_blank");
      a.setStyleName("");
      btmmenu.add(new InlineLabel(" | "));
      btmmenu.add(a);
    }
    btmmenu.add(new InlineLabel(" | "));
    btmmenu.add(new InlineLabel(C.keyHelp()));
  }

  private void onModuleLoad2(HostPageData hpd) {
    RESOURCES.gwt_override().ensureInjected();
    RESOURCES.css().ensureInjected();

    topMenu = RootPanel.get("gerrit_topmenu");
    final RootPanel gStarting = RootPanel.get("gerrit_startinggerrit");
    final RootPanel gBody = RootPanel.get("gerrit_body");
    bottomMenu = RootPanel.get("gerrit_btmmenu");

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

    final Grid menuLine = new Grid(1, 3);
    menuLeft = new MorphingTabPanel();
    menuRight = new LinkMenuBar();
    searchPanel = new SearchPanel();
    menuLeft.setStyleName(RESOURCES.css().topmenuMenuLeft());
    menuLine.setStyleName(RESOURCES.css().topmenu());
    topMenu.add(menuLine);
    final FlowPanel menuRightPanel = new FlowPanel();
    menuRightPanel.setStyleName(RESOURCES.css().topmenuMenuRight());
    menuRightPanel.add(searchPanel);
    menuRightPanel.add(menuRight);
    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) {
        String token = view.getToken();
        History.newItem(token, false);
        dispatchHistoryHooks(token);

        if (view instanceof ChangeListScreen) {
          lastChangeListToken = token;
        }

        super.onShowView(view);
        view.onShowView();
        lastViewToken = token;
      }
    };
    gBody.add(body);

    JsonUtil.addRpcStartHandler(RpcStatus.INSTANCE);
    JsonUtil.addRpcCompleteHandler(RpcStatus.INSTANCE);

    gStarting.getElement().getParentElement().removeChild(
        gStarting.getElement());
    RootPanel.detachNow(gStarting);
    ApiGlue.init();

    applyUserPreferences();
    populateBottomMenu(bottomMenu, hpd);
    refreshMenuBar();

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

    saveDefaultTheme();
    if (hpd.messages != null) {
      new MessageOfTheDayBar(hpd.messages).show();
    }
    PluginLoader.load(hpd.plugins,
        hpd.pluginsLoadTimeout,
        new GerritCallback<VoidResult>() {
          @Override
          public void onSuccess(VoidResult result) {
            String token = History.getToken();
            if (token.isEmpty()) {
              token = isSignedIn()
                  ? PageLinks.MINE
                  : PageLinks.toChangeQuery("status:open");
            }
            display(token);
          }
        });
  }

  private void saveDefaultTheme() {
    THEMER.init(Document.get().getElementById("gerrit_sitecss"),
        Document.get().getElementById("gerrit_header"),
        Document.get().getElementById("gerrit_footer"));
  }

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

    menuBars = new HashMap<>();

    boolean signedIn = isSignedIn();
    AuthInfo authInfo = info().auth();
    LinkMenuBar m;

    m = new LinkMenuBar();
    menuBars.put(GerritTopMenu.ALL.menuName, m);
    addLink(m, C.menuAllOpen(), PageLinks.toChangeQuery("status:open"));
    addLink(m, C.menuAllMerged(), PageLinks.toChangeQuery("status:merged"));
    addLink(m, C.menuAllAbandoned(), PageLinks.toChangeQuery("status:abandoned"));
    menuLeft.add(m, C.menuAll());

    if (signedIn) {
      LinkMenuBar myBar = new LinkMenuBar();
      menuBars.put(GerritTopMenu.MY.menuName, myBar);

      if (myPrefs.my() != null) {
        myBar.clear();
        String url = null;
        List<TopMenuItem> myMenuItems = Natives.asList(myPrefs.my());
        if (!myMenuItems.isEmpty()) {
          if (myMenuItems.get(0).getUrl().startsWith("#")) {
            url = myMenuItems.get(0).getUrl().substring(1);
          }
          for (TopMenuItem item : myMenuItems) {
            addExtensionLink(myBar, item);
          }
        }
        defaultScreenToken = url;
      }

      menuLeft.add(myBar, C.menuMine());
      menuLeft.selectTab(1);
    } else {
      menuLeft.selectTab(0);
    }

    final LinkMenuBar projectsBar = new LinkMenuBar();
    menuBars.put(GerritTopMenu.PROJECTS.menuName, projectsBar);
    addLink(projectsBar, C.menuProjectsList(), PageLinks.ADMIN_PROJECTS);
    projectsBar.addItem(new ProjectLinkMenuItem(C.menuProjectsInfo(), ProjectScreen.INFO));
    projectsBar.addItem(new ProjectLinkMenuItem(C.menuProjectsBranches(), ProjectScreen.BRANCHES));
    projectsBar.addItem(new ProjectLinkMenuItem(C.menuProjectsTags(), ProjectScreen.TAGS));
    projectsBar.addItem(new ProjectLinkMenuItem(C.menuProjectsAccess(), ProjectScreen.ACCESS));
    final LinkMenuItem dashboardsMenuItem =
        new ProjectLinkMenuItem(C.menuProjectsDashboards(),
            ProjectScreen.DASHBOARDS) {
      @Override
      protected boolean match(String token) {
        return super.match(token) ||
            (!getTargetHistoryToken().isEmpty() && ("/admin" + token).startsWith(getTargetHistoryToken()));
      }
    };
    projectsBar.addItem(dashboardsMenuItem);
    menuLeft.add(projectsBar, C.menuProjects());

    if (signedIn) {
      final LinkMenuBar peopleBar = new LinkMenuBar();
      menuBars.put(GerritTopMenu.PEOPLE.menuName, peopleBar);
      final LinkMenuItem groupsListMenuItem =
          addLink(peopleBar, C.menuPeopleGroupsList(), PageLinks.ADMIN_GROUPS);
      menuLeft.add(peopleBar, C.menuPeople());

      final LinkMenuBar pluginsBar = new LinkMenuBar();
      menuBars.put(GerritTopMenu.PLUGINS.menuName, pluginsBar);
      AccountCapabilities.all(new GerritCallback<AccountCapabilities>() {
        @Override
        public void onSuccess(AccountCapabilities result) {
          if (result.canPerform(CREATE_PROJECT)) {
            insertLink(projectsBar, C.menuProjectsCreate(),
                PageLinks.ADMIN_CREATE_PROJECT,
                projectsBar.getWidgetIndex(dashboardsMenuItem) + 1);
          }
          if (result.canPerform(CREATE_GROUP)) {
            insertLink(peopleBar, C.menuPeopleGroupsCreate(),
                PageLinks.ADMIN_CREATE_GROUP,
                peopleBar.getWidgetIndex(groupsListMenuItem) + 1);
          }
          if (result.canPerform(VIEW_PLUGINS)) {
            insertLink(pluginsBar, C.menuPluginsInstalled(),
                PageLinks.ADMIN_PLUGINS, 0);
            menuLeft.insert(pluginsBar, C.menuPlugins(),
                menuLeft.getWidgetIndex(peopleBar) + 1);
          }
        }
      }, CREATE_PROJECT, CREATE_GROUP, VIEW_PLUGINS);
    }

    if (hasDocumentation) {
      m = new LinkMenuBar();
      menuBars.put(GerritTopMenu.DOCUMENTATION.menuName, m);
      addDocLink(m, C.menuDocumentationTOC(), "index.html");
      addDocLink(m, C.menuDocumentationSearch(), "user-search.html");
      addDocLink(m, C.menuDocumentationUpload(), "user-upload.html");
      addDocLink(m, C.menuDocumentationAccess(), "access-control.html");
      addDocLink(m, C.menuDocumentationAPI(), "rest-api.html");
      addDocLink(m, C.menuDocumentationProjectOwnerGuide(), "intro-project-owner.html");
      menuLeft.add(m, C.menuDocumentation());
    }

    if (signedIn) {
      whoAmI(!authInfo.isClientSslCertLdap());
    } else {
      switch (authInfo.authType()) {
        case CLIENT_SSL_CERT_LDAP:
          break;

        case OPENID:
          menuRight.addItem(C.menuRegister(), new Command() {
            @Override
            public void execute() {
              String t = History.getToken();
              if (t == null) {
                t = "";
              }
              doSignIn(PageLinks.REGISTER + t);
            }
          });
          menuRight.addItem(C.menuSignIn(), new Command() {
            @Override
            public void execute() {
              doSignIn(History.getToken());
            }
          });
          break;

        case OAUTH:
          menuRight.addItem(C.menuSignIn(), new Command() {
            @Override
            public void execute() {
              doSignIn(History.getToken());
            }
          });
          break;

        case OPENID_SSO:
          menuRight.addItem(C.menuSignIn(), new Command() {
            @Override
            public void execute() {
              doSignIn(History.getToken());
            }
          });
          break;

        case HTTP:
        case HTTP_LDAP:
          if (authInfo.loginUrl() != null) {
            String signinText = authInfo.loginText() == null
                ? C.menuSignIn()
                : authInfo.loginText();
            menuRight.add(anchor(signinText, authInfo.loginUrl()));
          }
          break;

        case LDAP:
        case LDAP_BIND:
        case CUSTOM_EXTENSION:
          if (authInfo.registerUrl() != null) {
            String registerText = authInfo.registerText() == null
                ? C.menuRegister()
                : authInfo.registerText();
            menuRight.add(anchor(registerText, authInfo.registerUrl()));
          }
          menuRight.addItem(C.menuSignIn(), new Command() {
            @Override
            public void execute() {
              doSignIn(History.getToken());
            }
          });
          break;

        case DEVELOPMENT_BECOME_ANY_ACCOUNT:
          menuRight.add(anchor("Become", loginRedirect("")));
          break;
      }
    }
    ConfigServerApi.topMenus(new GerritCallback<TopMenuList>() {
      @Override
      public void onSuccess(TopMenuList result) {
        List<TopMenu> topMenuExtensions = Natives.asList(result);
        for (TopMenu menu : topMenuExtensions) {
          String name = menu.getName();
          LinkMenuBar existingBar = menuBars.get(name);
          LinkMenuBar bar =
              existingBar != null ? existingBar : new LinkMenuBar();
          for (TopMenuItem item : Natives.asList(menu.getItems())) {
            addMenuLink(bar, item);
          }
          if (existingBar == null) {
            menuBars.put(name, bar);
            menuLeft.add(bar, name);
          }
        }
      }
    });
  }

  public static void refreshUserPreferences() {
    if (isSignedIn()) {
      AccountApi.self().view("preferences")
          .get(new GerritCallback<GeneralPreferences>() {
            @Override
            public void onSuccess(GeneralPreferences prefs) {
              setUserPreferences(prefs);
            }
          });
    } else {
      setUserPreferences(GeneralPreferences.createDefault());
    }
  }

  public static void setUserPreferences(GeneralPreferences prefs) {
    myPrefs = prefs;
    applyUserPreferences();
    refreshMenuBar();
  }

  private static void applyUserPreferences() {
    CopyableLabel.setFlashEnabled(myPrefs.useFlashClipboard());
    if (siteHeader != null) {
      siteHeader.setVisible(myPrefs.showSiteHeader());
    }
    if (siteFooter != null) {
      siteFooter.setVisible(myPrefs.showSiteHeader());
    }
    FormatUtil.setPreferences(myPrefs);
    urlAliasMatcher.updateUserAliases(myPrefs.urlAliases());
  }

  public static boolean hasDocSearch() {
    return docSearch;
  }

  private static void getDocIndex(final AsyncCallback<DocInfo> cb) {
    RequestBuilder req =
        new RequestBuilder(RequestBuilder.HEAD, GWT.getHostPageBaseURL()
            + INDEX);
    req.setCallback(new RequestCallback() {
      @Override
      public void onResponseReceived(Request req, Response resp) {
        switch (resp.getStatusCode()) {
          case Response.SC_OK:
          case Response.SC_MOVED_PERMANENTLY:
          case Response.SC_MOVED_TEMPORARILY:
            cb.onSuccess(DocInfo.create());
            break;
          default:
            cb.onSuccess(null);
            break;
        }
      }

      @Override
      public void onError(Request request, Throwable e) {
        cb.onFailure(e);
      }
    });
    try {
      req.send();
    } catch (RequestException e) {
      cb.onFailure(e);
    }
  }

  private static void whoAmI(boolean canLogOut) {
    AccountInfo account = getUserAccount();
    final UserPopupPanel userPopup =
        new UserPopupPanel(account, canLogOut, true);
    final FlowPanel userSummaryPanel = new FlowPanel();
    class PopupHandler implements KeyDownHandler, ClickHandler {
      private void showHidePopup() {
        if (userPopup.isShowing() && userPopup.isVisible()) {
          userPopup.hide();
        } else {
          userPopup.showRelativeTo(userSummaryPanel);
        }
      }

      @Override
      public void onClick(ClickEvent event) {
        showHidePopup();
      }

      @Override
      public void onKeyDown(KeyDownEvent event) {
        if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
          showHidePopup();
          event.preventDefault();
        }
      }
    }
    final PopupHandler popupHandler = new PopupHandler();
    final InlineLabel l = new InlineLabel(FormatUtil.name(account));
    l.setStyleName(RESOURCES.css().menuBarUserName());
    final AvatarImage avatar = new AvatarImage(account, 26, false);
    avatar.setStyleName(RESOURCES.css().menuBarUserNameAvatar());
    userSummaryPanel.setStyleName(RESOURCES.css().menuBarUserNamePanel());
    userSummaryPanel.add(l);
    userSummaryPanel.add(avatar);
    // "BLACK DOWN-POINTING SMALL TRIANGLE"
    userSummaryPanel.add(new InlineLabel(" \u25be"));
    userPopup.addAutoHidePartner(userSummaryPanel.getElement());
    FocusPanel fp = new FocusPanel(userSummaryPanel);
    fp.setStyleName(RESOURCES.css().menuBarUserNameFocusPanel());
    fp.addKeyDownHandler(popupHandler);
    fp.addClickHandler(popupHandler);
    menuRight.add(fp);
  }

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

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

  private static void insertLink(final LinkMenuBar m, final String text,
      final String historyToken, final int beforeIndex) {
    m.insertItem(new LinkMenuItem(text, historyToken), beforeIndex);
  }

  private static LinkMenuItem addProjectLink(LinkMenuBar m, TopMenuItem item) {
    LinkMenuItem i = new ProjectLinkMenuItem(item.getName(), item.getUrl()) {
        @Override
        protected void onScreenLoad(Project.NameKey project) {
        String p =
            panel.replace(PROJECT_NAME_MENU_VAR,
                URL.encodeQueryString(project.get()));
          if (!panel.startsWith("/x/") && !isAbsolute(panel)) {
            UrlBuilder builder = new UrlBuilder();
            builder.setProtocol(Location.getProtocol());
            builder.setHost(Location.getHost());
            String port = Location.getPort();
            if (port != null && !port.isEmpty()) {
              builder.setPort(Integer.parseInt(port));
            }
            builder.setPath(Location.getPath());
            p = builder.buildString() + p;
          }
          getElement().setPropertyString("href", p);
        }

        @Override
        public void go() {
          String href = getElement().getPropertyString("href");
          if (href.startsWith("#")) {
            super.go();
          } else {
            Window.open(href, getElement().getPropertyString("target"), "");
          }
        }
      };
    if (item.getTarget() != null && !item.getTarget().isEmpty()) {
      i.getElement().setAttribute("target", item.getTarget());
    }
    if (item.getId() != null) {
      i.getElement().setAttribute("id", item.getId());
    }
    m.addItem(i);
    return i;
  }

  private static void addDocLink(final LinkMenuBar m, final String text,
      final String href) {
    final Anchor atag = anchor(text, docUrl + href);
    atag.setTarget("_blank");
    m.add(atag);
  }

  private static void addMenuLink(LinkMenuBar m, TopMenuItem item) {
    if (item.getUrl().contains(PROJECT_NAME_MENU_VAR)) {
      addProjectLink(m, item);
    } else {
      addExtensionLink(m, item);
    }
  }

  private static void addExtensionLink(LinkMenuBar m, TopMenuItem item) {
    if (item.getUrl().startsWith("#")
        && (item.getTarget() == null || item.getTarget().isEmpty())) {
      LinkMenuItem a =
          new LinkMenuItem(item.getName(), item.getUrl().substring(1));
      if (item.getId() != null) {
        a.getElement().setAttribute("id", item.getId());
      }
      m.addItem(a);
    } else {
      Anchor atag = anchor(item.getName(), isAbsolute(item.getUrl())
          ? item.getUrl()
          : selfRedirect(item.getUrl()));
      if (item.getTarget() != null && !item.getTarget().isEmpty()) {
        atag.setTarget(item.getTarget());
      }
      if (item.getId() != null) {
        atag.getElement().setAttribute("id", item.getId());
      }
      m.add(atag);
    }
  }

  private static boolean isAbsolute(String url) {
    return url.matches("^https?://.*");
  }
}
