// Copyright 2010-2014, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "session/session_usage_observer.h"

#include <climits>
#include <map>
#include <string>
#include <vector>

#include "base/logging.h"
#include "base/mutex.h"
#include "base/number_util.h"
#include "base/port.h"
#include "base/scheduler.h"
#include "base/singleton.h"
#include "base/util.h"
#include "config/stats_config_util.h"
#include "session/commands.pb.h"
#include "session/state.pb.h"
#include "usage_stats/usage_stats.h"
#include "usage_stats/usage_stats.pb.h"

using mozc::usage_stats::UsageStats;

namespace mozc {
namespace session {

namespace {
Mutex g_stats_cache_mutex;  // NOLINT
const char kStatsJobName[] = "SaveCachedStats";
const uint32 kSaveCacheStatsInterval = 10 * 60 * 1000;  // 10 min

const size_t kMaxSession = 64;

// Adds double value to DoubleValueStats.
// DoubleValueStats contains (num, total, square_total).
void AddToDoubleValueStats(
    double value,
    usage_stats::Stats::DoubleValueStats *double_stats) {
  DCHECK(double_stats);
  double_stats->set_num(double_stats->num() + 1);
  double_stats->set_total(double_stats->total() + value);
  double_stats->set_square_total(double_stats->square_total() + value * value);
}

uint64 GetTimeInMilliSecond() {
  uint64 second = 0;
  uint32 micro_second = 0;
  Util::GetTimeOfDay(&second, &micro_second);
  return second * 1000 + micro_second / 1000;
}

uint32 GetDuration(uint64 base_value) {
  const uint64 result = GetTimeInMilliSecond() - base_value;
  if (result != static_cast<uint32>(result)) {
    return kuint32max;
  }
  return result;
}

bool IsSessionIndependentCommand(commands::Input::CommandType type) {
  switch (type) {
    case commands::Input::NO_OPERATION:
    case commands::Input::SET_CONFIG:
    case commands::Input::GET_CONFIG:
    case commands::Input::SET_IMPOSED_CONFIG:
    case commands::Input::CLEAR_USER_HISTORY:
    case commands::Input::CLEAR_USER_PREDICTION:
    case commands::Input::CLEAR_UNUSED_USER_PREDICTION:
    case commands::Input::CLEAR_STORAGE:
    case commands::Input::READ_ALL_FROM_STORAGE:
    case commands::Input::RELOAD:
    case commands::Input::SEND_USER_DICTIONARY_COMMAND:
      return true;
    default:
      return false;
  }
}
}  // namespace

SessionUsageObserver::SessionUsageObserver() {
  Scheduler::AddJob(Scheduler::JobSetting(
      kStatsJobName,
      kSaveCacheStatsInterval,  // default interval
      kSaveCacheStatsInterval,  // max interval
      kSaveCacheStatsInterval,  // delay start
      0,  // random delay 0 (no internet connection from this job)
      &SessionUsageObserver::SaveCachedStats,
      &usage_cache_));
}

SessionUsageObserver::~SessionUsageObserver() {
  SaveCachedStats(&usage_cache_);
  Scheduler::RemoveJob(kStatsJobName);
}

void SessionUsageObserver::UsageCache::Clear() {
  touch_event.clear();
  miss_touch_event.clear();
}

// static
bool SessionUsageObserver::SaveCachedStats(void *data) {
  UsageCache *cache = reinterpret_cast<UsageCache *>(data);

  {
    scoped_lock l(&g_stats_cache_mutex);
    if (!cache->touch_event.empty()) {
      UsageStats::StoreTouchEventStats(
          "VirtualKeyboardStats", cache->touch_event);
    }
    if (!cache->miss_touch_event.empty()) {
      UsageStats::StoreTouchEventStats(
          "VirtualKeyboardMissStats", cache->miss_touch_event);
    }
    cache->Clear();
  }

  if (!UsageStats::Sync()) {
    LOG(ERROR) << "Updated internal cache of UsageStats but "
               << "failed to sync its data to disk";
    return false;
  } else {
    VLOG(3) << "Save Stats";
    return true;
  }
}

void SessionUsageObserver::EvalCreateSession(
    const commands::Input &input, const commands::Output &output,
    map<uint64, SessionState> *states) {
  // Number of create session
  SessionState state;
  state.set_id(output.id());
  state.set_created_time(GetTimeInMilliSecond());
  // TODO(toshiyuki): LRU?
  if (states->size() <= kMaxSession) {
    states->insert(make_pair(output.id(), state));
  }
}

void SessionUsageObserver::UpdateState(const commands::Input &input,
                                       const commands::Output &output,
                                       SessionState *state) {
  // Preedit
  if (!state->has_preedit() && output.has_preedit()) {
    // Start preedit
    state->set_start_preedit_time(GetTimeInMilliSecond());
  } else if (state->has_preedit() && output.has_preedit()) {
    // Continue preedit
  } else if (state->has_preedit() && !output.has_preedit()) {
    // Finish preedit
    UsageStats::UpdateTiming("PreeditDurationMSec",
                             GetDuration(state->start_preedit_time()));
  } else {
    // no preedit
  }

  // Candidates
  if (!state->has_candidates() && output.has_candidates()) {
    const commands::Candidates &cands = output.candidates();
    switch (cands.category()) {
      case commands::CONVERSION:
        state->set_start_conversion_window_time(GetTimeInMilliSecond());
        break;
      case commands::PREDICTION:
        state->set_start_prediction_window_time(GetTimeInMilliSecond());
        break;
      case commands::SUGGESTION:
        state->set_start_suggestion_window_time(GetTimeInMilliSecond());
        break;
      default:
        LOG(WARNING) << "candidate window has invalid category";
        break;
    }
  } else if (state->has_candidates() &&
             state->candidates().category() == commands::SUGGESTION) {
    if (!output.has_candidates() ||
        output.candidates().category() != commands::SUGGESTION) {
      const uint32 suggestion_duration =
          GetDuration(state->start_suggestion_window_time());
      UsageStats::UpdateTiming("SuggestionWindowDurationMSec",
                               suggestion_duration);
    }
    if (output.has_candidates()) {
      switch (output.candidates().category()) {
        case commands::CONVERSION:
        state->set_start_conversion_window_time(GetTimeInMilliSecond());
          break;
        case commands::PREDICTION:
          state->set_start_prediction_window_time(GetTimeInMilliSecond());
          break;
        case commands::SUGGESTION:
          // continue suggestion
          break;
        default:
          LOG(WARNING) << "candidate window has invalid category";
          break;
      }
    }
  } else if (state->has_candidates() &&
             state->candidates().category() == commands::PREDICTION) {
    if (!output.has_candidates() ||
        output.candidates().category() != commands::PREDICTION) {
      const uint64 predict_duration =
          GetDuration(state->start_prediction_window_time());
      UsageStats::UpdateTiming("PredictionWindowDurationMSec",
                               predict_duration);
    }
    // no transition
  } else if (state->has_candidates() &&
             state->candidates().category() == commands::CONVERSION) {
    if (!output.has_candidates() ||
        output.candidates().category() != commands::CONVERSION) {
      const uint32 conversion_duration =
          GetDuration(state->start_conversion_window_time());
      UsageStats::UpdateTiming("ConversionWindowDurationMSec",
                               conversion_duration);
    }
    // no transition
  }

  // Cascading window
  if ((!state->has_candidates() ||
       (state->has_candidates() &&
        !state->candidates().has_subcandidates())) &&
      output.has_candidates() && output.candidates().has_subcandidates()) {
    UsageStats::IncrementCount("ShowCascadingWindow");
  }

  // Update Preedit
  if (output.has_preedit()) {
    state->mutable_preedit()->CopyFrom(output.preedit());
  } else {
    state->clear_preedit();
  }

  // Update Candidates
  if (output.has_candidates()) {
    state->mutable_candidates()->CopyFrom(output.candidates());
  } else {
    state->clear_candidates();
  }

  if ((!state->has_result() ||
       state->result().type() != commands::Result::STRING) &&
      output.has_result() &&
      output.result().type() == commands::Result::STRING) {
    state->set_committed(true);
  }

  // Update Result
  if (output.has_result()) {
    state->mutable_result()->CopyFrom(output.result());
  } else {
    state->clear_result();
  }
}

void SessionUsageObserver::UpdateClientSideStats(const commands::Input &input,
                                                 SessionState *state) {
  // TODO(hsumita): Extract GetEnumValueName and CamelCaseString as public
  //                method from SessionUsageStatsUtil and use it.

  switch (input.command().usage_stats_event()) {
    case commands::SessionCommand::INFOLIST_WINDOW_SHOW:
      if (!state->has_start_infolist_window_time()) {
        state->set_start_infolist_window_time(GetTimeInMilliSecond());
      }
      break;
    case commands::SessionCommand::INFOLIST_WINDOW_HIDE:
      if (state->has_start_infolist_window_time()) {
        const uint64 infolist_duration =
            GetDuration(state->start_infolist_window_time());
        UsageStats::UpdateTiming("InfolistWindowDurationMSec",
                                 infolist_duration);
        state->clear_start_infolist_window_time();
      }
      break;
    case commands::SessionCommand::HANDWRITING_OPEN_EVENT:
      UsageStats::IncrementCount("HandwritingOpen");
      break;
    case commands::SessionCommand::HANDWRITING_COMMIT_EVENT:
      UsageStats::IncrementCount("HandwritingCommit");
      break;
    case commands::SessionCommand::CHARACTER_PALETTE_OPEN_EVENT:
      UsageStats::IncrementCount("CharacterPaletteOpen");
      break;
    case commands::SessionCommand::CHARACTER_PALETTE_COMMIT_EVENT:
      UsageStats::IncrementCount("CharacterPaletteCommit");
      break;
    case commands::SessionCommand::SOFTWARE_KEYBOARD_LAYOUT_LANDSCAPE:
      LOG_IF(DFATAL, !input.command().has_usage_stats_event_int_value())
          << "SOFTWARE_KEYBOARD_LAYOUT_LANDSCAPE stats must have int value.";
      UsageStats::SetInteger("SoftwareKeyboardLayoutLandscape",
                             input.command().usage_stats_event_int_value());
      break;
    case commands::SessionCommand::SOFTWARE_KEYBOARD_LAYOUT_PORTRAIT:
      LOG_IF(DFATAL, !input.command().has_usage_stats_event_int_value())
          << "SOFTWARE_KEYBOARD_LAYOUT_PORTRAIT stats must have int value.";
      UsageStats::SetInteger("SoftwareKeyboardLayoutPortrait",
                             input.command().usage_stats_event_int_value());
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_0:
      UsageStats::IncrementCount("SubmittedCandidateRow0");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_1:
      UsageStats::IncrementCount("SubmittedCandidateRow1");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_2:
      UsageStats::IncrementCount("SubmittedCandidateRow2");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_3:
      UsageStats::IncrementCount("SubmittedCandidateRow3");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_4:
      UsageStats::IncrementCount("SubmittedCandidateRow4");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_5:
      UsageStats::IncrementCount("SubmittedCandidateRow5");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_6:
      UsageStats::IncrementCount("SubmittedCandidateRow6");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_7:
      UsageStats::IncrementCount("SubmittedCandidateRow7");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_8:
      UsageStats::IncrementCount("SubmittedCandidateRow8");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_9:
      UsageStats::IncrementCount("SubmittedCandidateRow9");
      break;
    case commands::SessionCommand::SUBMITTED_CANDIDATE_ROW_GE10:
      UsageStats::IncrementCount("SubmittedCandidateRowGE10");
      break;
    case commands::SessionCommand::KEYBOARD_FOLD_EVENT:
      UsageStats::IncrementCount("KeyboardFoldEvent");
      break;
    case commands::SessionCommand::KEYBOARD_EXPAND_EVENT:
      UsageStats::IncrementCount("KeyboardExpandEvent");
      break;
    default:
      LOG(WARNING) << "client side usage stats event has invalid category";
      break;
  }
}

void SessionUsageObserver::StoreTouchEventStats(
    const commands::Input::TouchEvent &touch_event,
    usage_stats::TouchEventStatsMap *touch_event_stats_map) {
  if (!config::StatsConfigUtil::IsEnabled()) {
    return;
  }
  scoped_lock l(&g_stats_cache_mutex);

  usage_stats::Stats::TouchEventStats *touch_event_stats =
      &(*touch_event_stats_map)[touch_event.source_id()];
  if (!touch_event_stats->has_source_id()) {
    touch_event_stats->set_source_id(touch_event.source_id());
  }
  if (touch_event.stroke_size() > 0) {
    const commands::Input::TouchPosition &first_pos = touch_event.stroke(0);
    const commands::Input::TouchPosition &last_pos =
        touch_event.stroke(touch_event.stroke_size() - 1);
    AddToDoubleValueStats(first_pos.x(),
                          touch_event_stats->mutable_start_x_stats());
    AddToDoubleValueStats(last_pos.x() - first_pos.x(),
                          touch_event_stats->mutable_direction_x_stats());
    AddToDoubleValueStats(first_pos.y(),
                          touch_event_stats->mutable_start_y_stats());
    AddToDoubleValueStats(last_pos.y() - first_pos.y(),
                          touch_event_stats->mutable_direction_y_stats());
    AddToDoubleValueStats(
        (last_pos.timestamp() - first_pos.timestamp()) / 1000.0,
        touch_event_stats->mutable_time_length_stats());
  }
}

void SessionUsageObserver::LogTouchEvent(const commands::Input &input,
                                         const commands::Output &output,
                                         const SessionState &state) {
  // When the input field type is PASSWORD, do not log the touch events.
  if (state.has_input_field_type() &&
      (state.input_field_type() == commands::Context::PASSWORD)) {
    return;
  }

  if (!state.has_request() || !state.request().has_keyboard_name()) {
    return;
  }
  const string &keyboard_name = state.request().keyboard_name();

  // When last_touchevents_ is not empty and BACKSPACE is pressed,
  // save last_touchevents_ as miss_touch_event.
  if (!last_touchevents_.empty() &&
      input.has_key() && input.key().has_special_key() &&
      input.key().special_key() == commands::KeyEvent::BACKSPACE &&
      state.has_preedit()) {
    for (size_t i = 0; i < last_touchevents_.size(); ++i) {
      StoreTouchEventStats(last_touchevents_[i],
                           &usage_cache_.miss_touch_event[keyboard_name]);
    }
    last_touchevents_.clear();
  }

  // When last_touchevents_ is not empty and any kind of commands are send
  // except for EXPAND_SUGGESTION, save last_touchevents_ as touch_event.
  // It is because EXPAND_SUGGESTION is automatically send from Java side codes.
  if (!last_touchevents_.empty() &&
      !((input.type() == commands::Input::SEND_COMMAND) &&
        (input.has_command()) && (input.command().has_type()) &&
        (input.command().type() ==
         commands::SessionCommand::EXPAND_SUGGESTION))) {
    for (size_t i = 0; i < last_touchevents_.size(); ++i) {
      StoreTouchEventStats(last_touchevents_[i],
                           &usage_cache_.touch_event[keyboard_name]);
    }
    last_touchevents_.clear();
  }

  if (input.touch_events_size() > 0) {
    if (input.type() == commands::Input::SEND_KEY) {
      // When the input command contains TouchEvent and the type is SEND_KEY,
      // save the TouchEvent to last_touchevents_.
      // This last_touchevents_ will be aggregated to touch_event_stat_cache_
      // or miss_touch_event_stat_cache_ and be cleared when the subsequent
      // command will be recieved.
      for (size_t i = 0; i < input.touch_events_size(); ++i) {
        last_touchevents_.push_back(input.touch_events(i));
      }
    } else {
      // When the input command contains TouchEvent and the type isn't SEND_KEY,
      // save the TouchEvent to touch_event_stat_cache_.
      for (size_t i = 0; i < input.touch_events_size(); ++i) {
        StoreTouchEventStats(input.touch_events(i),
                             &usage_cache_.touch_event[keyboard_name]);
      }
    }
  }
}

void SessionUsageObserver::EvalCommandHandler(
    const commands::Command &command) {
  const commands::Input &input = command.input();
  const commands::Output &output = command.output();

  if (input.type() == commands::Input::CREATE_SESSION) {
    EvalCreateSession(input, output, &states_);
    SaveCachedStats(&usage_cache_);
    return;
  }

  // Session independent command usually has no session ID.
  if (IsSessionIndependentCommand(input.type())) {
    return;
  } else if (!input.has_id()) {
    LOG(WARNING) << "no id";
    // Should have id
    return;
  }

  if (input.id() == 0) {
    VLOG(3) << "id == 0";
    return;
  }

  map<uint64, SessionState>::iterator iter = states_.find(input.id());
  if (iter == states_.end()) {
    LOG(WARNING) << "unknown session";
    // Unknown session
    return;
  }
  SessionState *state = &iter->second;
  DCHECK(state);

  if (input.type() == commands::Input::DELETE_SESSION) {
    const uint32 session_duration = GetDuration(state->created_time());
    UsageStats::UpdateTiming("SessionDurationMSec", session_duration);

    states_.erase(iter);
    SaveCachedStats(&usage_cache_);
    return;
  }

  // Backspace key after commit
  if (state->committed() &&
      // for Applications supporting TEST_SEND_KEY
      (input.type() == commands::Input::TEST_SEND_KEY ||
       // other Applications
       input.type() == commands::Input::SEND_KEY)) {
    if (input.has_key() && input.key().has_special_key() &&
        input.key().special_key() == commands::KeyEvent::BACKSPACE &&
        state->has_result() &&
        state->result().type() == commands::Result::STRING) {
      UsageStats::IncrementCount("BackSpaceAfterCommit");
      // Count only one for each submitted result.
    }
    state->set_committed(false);
  }

  // Client side event
  if ((input.type() == commands::Input::SEND_COMMAND) &&
      (input.has_command()) &&
      (input.command().type() ==
       commands::SessionCommand::USAGE_STATS_EVENT) &&
      (input.command().has_usage_stats_event())) {
    UpdateClientSideStats(input, state);
  }

  // Evals touch events and saves touch event stats.
  LogTouchEvent(input, output, *state);

  if ((input.type() == commands::Input::SEND_COMMAND ||
       input.type() == commands::Input::SEND_KEY) &&
      output.has_consumed() &&
      output.consumed()) {
    // update states only when input was consumed
    UpdateState(input, output, state);
  }
  if (input.type() == commands::Input::SET_REQUEST) {
    if (input.has_request()) {
      state->mutable_request()->CopyFrom(input.request());
    }
  }
  // Saves input field type
  if ((input.type() == commands::Input::SEND_COMMAND) &&
      (input.has_command()) &&
      (input.command().type() ==
       commands::SessionCommand::SWITCH_INPUT_FIELD_TYPE) &&
      (input.context().has_input_field_type())) {
    state->set_input_field_type(input.context().input_field_type());
  }
}

void SessionUsageObserver::Reload() {
}

}  // namespace session
}  // namespace mozc
