// Copyright (C) 2014 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.gitblit;

import java.util.Arrays;
import java.util.List;

import com.google.common.collect.Lists;
import com.google.gerrit.extensions.annotations.PluginCanonicalWebUrl;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.client.GerritTopMenu;
import com.google.gerrit.extensions.webui.TopMenu;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;

public class GitBlitTopMenu implements TopMenu {

  // Not configurable to avoid mis-configurations clashing with predefined top
  // menus.
  private static final String GITBLIT_TOPMENU_NAME = "GitBlit";

  private final MenuEntry fullMenuEntries;
  private final MenuEntry restrictedMenuEntries;
  private final MenuEntry extraProjectEntries;
  private final Provider<CurrentUser> userProvider;

  @Inject
  public GitBlitTopMenu(@PluginName String pluginName,
      @PluginCanonicalWebUrl String pluginUrl,
      Provider<CurrentUser> userProvider,
      PluginConfigFactory cfgProvider) {
    this.userProvider = userProvider;

    String gitBlitBaseUrl = pluginUrl;
    PluginConfig cfg = cfgProvider.getFromGerritConfig(pluginName, true);
    // We don't have to worry about XSS here; the way these menu item get
    // created through GWT ensures that these values read from the config
    // end up as text nodes in the DOM, even if they contain potentially
    // malicious code. So if somebody sets these values to some HTML snippet,
    // he'll simply end up with a funny looking menu item, but he can't inject
    // things here.
    MenuItem repositories =
        new MenuItem(cfg.getString("repositories", "Repositories"),
            gitBlitBaseUrl + "repositories/", "");
    // GitBlit handles its own "/" url, so Gerrit won't produce any link, not even on the "plugins" page, that would display the documentation.
    // I've considered simply redirecting "/" to "/Documentation/" since GitBlit's "/" screen is very similar to its "/activity/" screen, but
    // decided finally to provide an explicit documentation submenu instead.
    MenuItem documentation = new MenuItem(cfg.getString("documentation", "Documentation"), gitBlitBaseUrl + "Documentation/", "");
    restrictedMenuEntries = new MenuEntry(GITBLIT_TOPMENU_NAME, Arrays.asList(repositories, documentation));
    List<MenuItem> fullMenuItems = Lists.newArrayList();
    fullMenuItems.add(repositories);
    fullMenuItems.add(new MenuItem(cfg.getString("activity", "Activity"),
        gitBlitBaseUrl + "activity/", ""));
    String search = cfg.getString("search");
    if (search != null && !search.isEmpty()) {
      fullMenuItems.add(new MenuItem(search, gitBlitBaseUrl + "lucene/", ""));
    }
    fullMenuItems.add(documentation);
    fullMenuEntries = new MenuEntry(GITBLIT_TOPMENU_NAME, fullMenuItems);
    extraProjectEntries =
        new MenuEntry(GerritTopMenu.PROJECTS, Arrays.asList(new MenuItem(cfg
            .getString("browse", "Browse"), gitBlitBaseUrl
            + "summary?r=${projectName}", "")));
  }

  @Override
  public List<MenuEntry> getEntries() {
    return Arrays.asList(userProvider.get().isIdentifiedUser()
        ? fullMenuEntries : restrictedMenuEntries, extraProjectEntries);
  }
}
