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

import com.google.common.base.Strings;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.annotations.RequiresCapability;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.webui.TopMenu;
import com.google.gerrit.server.config.ConfigResource;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
public class GetMenus implements RestReadView<ConfigResource>, TopMenu {
  public final static String SECTION_MENU_ITEM = "menuItem";
  public final static String KEY_TOP_MENU = "topMenu";
  public final static String KEY_NAME = "name";
  public final static String KEY_TARGET = "target";
  public final static String KEY_ID = "id";

  private final static String DEFAULT_TOP_MENU = "Extensions";

  private final File cfgFile;

  private volatile FileSnapshot cfgSnapshot;
  private volatile FileBasedConfig cfg;

  @Inject
  public GetMenus(@PluginName String pluginName, SitePaths sitePaths) {
    this.cfgFile = new File(sitePaths.etc_dir, pluginName + ".config");
  }

  @Override
  public List<TopMenu.MenuEntry> apply(ConfigResource rsrc) {
    return getEntries();
  }

  @Override
  public List<MenuEntry> getEntries() {
    if (cfg == null || cfgSnapshot.isModified(cfgFile)) {
      cfgSnapshot = FileSnapshot.save(cfgFile);
      cfg = new FileBasedConfig(cfgFile, FS.DETECTED);
      try {
        cfg.load();
      } catch (ConfigInvalidException | IOException e) {
        return Collections.emptyList();
      }
    }

    List<MenuEntry> menuEntries = new ArrayList<>();
    for (String url : cfg.getSubsections(SECTION_MENU_ITEM)) {
      String name = cfg.getString(SECTION_MENU_ITEM, url, KEY_NAME);
      if (Strings.isNullOrEmpty(name)) {
        continue;
      }

      String topMenu = cfg.getString(SECTION_MENU_ITEM, url, KEY_TOP_MENU);
      if (topMenu == null) {
        topMenu = DEFAULT_TOP_MENU;
      }

      String target = cfg.getString(SECTION_MENU_ITEM, url, KEY_TARGET);
      String id = cfg.getString(SECTION_MENU_ITEM, url, KEY_ID);

      menuEntries.add(new MenuEntry(topMenu,
          Collections.singletonList(new MenuItem(name, url, target, id))));
    }
    return menuEntries;
  }
}
