// Copyright 2011 Google Inc. All Rights Reserved.
//
// 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.enterprise.adaptor;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Provides performance data when responding to 
 * ajax calls from dashboard.
 */
class StatRpcMethod implements RpcHandler.RpcMethod {
  private String adaptorVersion = null;
  private String adaptorType;
  private Journal journal;
  private boolean isAdaptorIncremental;
  private File configFile;
  private static final Logger log
      = Logger.getLogger(StatRpcMethod.class.getName());

  public StatRpcMethod(Journal journal, Adaptor adaptor,
      boolean isAdaptorIncremental, File configFile) {
    this.journal = journal;
    this.isAdaptorIncremental = isAdaptorIncremental;
    this.configFile = configFile;

    Class adaptorClass = adaptor.getClass();
    if (adaptorClass.getPackage() != null) {
      adaptorVersion = adaptorClass.getPackage().getImplementationVersion();
    }
    adaptorType = adaptorClass.getSimpleName();
  }

  @Override
  public Object run(List request) {
    // TODO(ejona): choose locale based on Accept-Languages.
    Locale locale = Locale.ENGLISH;

    Journal.JournalSnapshot journalSnap = journal.getSnapshot();

    Map<String, Object> map = new TreeMap<String, Object>();

    {
      Map<String, Object> simple = new TreeMap<String, Object>();
      simple.put("isIncrementalSupported", isAdaptorIncremental);
      simple.put("numTotalDocIdsPushed", journalSnap.numTotalDocIdsPushed);
      simple.put("numUniqueDocIdsPushed", journalSnap.numUniqueDocIdsPushed);
      simple.put("numTotalGsaRequests", journalSnap.numTotalGsaRequests);
      simple.put("numUniqueGsaRequests", journalSnap.numUniqueGsaRequests);
      simple.put("numTotalNonGsaRequests", journalSnap.numTotalNonGsaRequests);
      simple.put("numUniqueNonGsaRequests",
                 journalSnap.numUniqueNonGsaRequests);
      simple.put("timeResolution", journalSnap.timeResolution);
      simple.put("lastSuccessfulFullPushStart",
                 journalSnap.lastSuccessfulFullPushStart);
      simple.put("lastSuccessfulFullPushEnd",
                 journalSnap.lastSuccessfulFullPushEnd);
      simple.put("currentFullPushStart", journalSnap.currentFullPushStart);
      simple.put("lastSuccessfulIncrementalPushStart",
                 journalSnap.lastSuccessfulIncrementalPushStart);
      simple.put("lastSuccessfulIncrementalPushEnd",
                 journalSnap.lastSuccessfulIncrementalPushEnd);
      simple.put("currentIncrementalPushStart",
                 journalSnap.currentIncrementalPushStart);
      simple.put("whenStarted", journalSnap.whenStarted);
      map.put("simpleStats", simple);
    }

    {
      Map<String, Object> versionMap = new TreeMap<String, Object>();

      versionMap.put("versionJvm", System.getProperty("java.version"));
      versionMap.put("versionAdaptorLibrary", getAdaptorLibraryVersion(locale));
      versionMap.put("typeAdaptor", adaptorType);
      versionMap.put("versionAdaptor", getAdaptorVersion(locale));
      versionMap.put("cwd", System.getProperty("user.dir"));
      versionMap.put("configFileName", getConfigFilename(locale));
      map.put("versionStats", versionMap);
    }

    {
      List<Object> statsList = new ArrayList<Object>();
      long currentTime = journalSnap.currentTime;
      for (Journal.Stats stats : journalSnap.timeStats) {
        Map<String, Object> stat = new TreeMap<String, Object>();
        stat.put("snapshotDuration", stats.snapshotDurationMs);
        stat.put("currentTime", currentTime);
        List<Map<String, Object>> statData
            = new ArrayList<Map<String, Object>>(stats.stats.length);
        long time = stats.pendingStatPeriodEnd;
        // Rewind to beginning
        time -= stats.stats.length * stats.snapshotDurationMs;
        for (int i = stats.currentStat + 1; i < stats.stats.length; i++) {
          statData.add(getStat(stats.stats[i], time));
          time += stats.snapshotDurationMs;
        }
        for (int i = 0; i <= stats.currentStat; i++) {
          statData.add(getStat(stats.stats[i], time));
          time += stats.snapshotDurationMs;
        }
        stat.put("statData", statData);
        statsList.add(stat);
      }
      map.put("stats", statsList);
    }

    return map;
  }

  private Map<String, Object> getStat(Journal.Stat stat, long time) {
    Map<String, Object> statMap = new TreeMap<String, Object>();
    statMap.put("time", time);
    statMap.put("requestProcessingsCount", stat.requestProcessingsCount);
    statMap.put("requestProcessingsDurationSum",
                stat.requestProcessingsDurationSum);
    statMap.put("requestProcessingsMaxDuration",
                stat.requestProcessingsMaxDuration);
    statMap.put("requestProcessingsThroughput",
                stat.requestProcessingsThroughput);
    return statMap;
  }

  private String getAdaptorLibraryVersion(Locale locale) {
    String version = this.getClass().getPackage().getImplementationVersion();
    return version == null
        ? Translation.STATS_VERSION_UNKNOWN.toString(locale) : version;
  }

  private String getAdaptorVersion(Locale locale) {
    return adaptorVersion == null
        ? Translation.STATS_VERSION_UNKNOWN.toString(locale) : adaptorVersion;
  }

  private String getConfigFilename(Locale locale) {
    File canonicalConfigFile = null;
    try {
      if (configFile != null) {
        canonicalConfigFile = configFile.getCanonicalFile();
      }
    } catch (IOException e) {
      log.log(Level.WARNING, "Could not determine file location for \""
          + configFile + "\"", e);
      // treat file as if it were not specified -- leave it null below
    }

    return canonicalConfigFile == null
        ? Translation.STATS_CONFIG_NONE.toString(locale)
        : canonicalConfigFile.toString();
  }
}
