// Copyright 2010-2015, 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 "win32/tip/tip_input_mode_manager.h"

#include <algorithm>

#include "win32/base/conversion_mode_util.h"
#include "win32/base/indicator_visibility_tracker.h"

namespace mozc {

typedef ::mozc::commands::CompositionMode CompositionMode;

namespace win32 {
namespace tsf {
namespace {

template <typename T>
void Dedup(vector<T> *container) {
  sort(container->begin(), container->end());
  auto new_end = unique(container->begin(), container->end());
  container->erase(new_end, container->end());
}

}  // namespace

TipInputModeManagerImpl::StatePair::StatePair()
    : open_close(false),
      conversion_mode(kHiragana) {}

TipInputModeManagerImpl::StatePair::StatePair(
    bool open_close, ConversionMode conversion_mode)
    : open_close(open_close),
      conversion_mode(conversion_mode) {}

TipInputModeManagerImpl::StatePair TipInputModeManagerImpl::GetOverriddenState(
    const StatePair &base_state,
    const vector<InputScope> &input_scopes) {
  if (input_scopes.empty()) {
    return base_state;
  }
  vector<ConversionMode> states;
  for (size_t i = 0; i < input_scopes.size(); ++i) {
    const InputScope input_scope = input_scopes[i];
    switch (input_scope) {
      // Some InputStope can be mapped to commands::Context::InputFieldType.
      // TODO(yukawa): Pass context information to the converter.
      case IS_URL:
      case IS_EMAIL_USERNAME:
      case IS_EMAIL_SMTPEMAILADDRESS:
      case IS_DIGITS:
      case IS_NUMBER:
      case IS_PASSWORD:
      case IS_TELEPHONE_FULLTELEPHONENUMBER:
      case IS_TELEPHONE_COUNTRYCODE:
      case IS_TELEPHONE_AREACODE:
      case IS_TELEPHONE_LOCALNUMBER:
      case IS_TIME_FULLTIME:
      case IS_TIME_HOUR:
      case IS_TIME_MINORSEC:
        states.push_back(kDirect);
        break;
      case IS_HIRAGANA:
        states.push_back(kHiragana);
        break;
      case IS_ALPHANUMERIC_HALFWIDTH:
        states.push_back(kHalfAscii);
        break;
      case IS_NUMBER_FULLWIDTH:
      case IS_ALPHANUMERIC_FULLWIDTH:
        states.push_back(kFullAscii);
        break;
      case IS_KATAKANA_HALFWIDTH:
        states.push_back(kHalfKatakana);
        break;
      case IS_KATAKANA_FULLWIDTH:
        states.push_back(kFullKatakana);
        break;
      default:
        break;
    }
  }
  if (states.empty()) {
    return base_state;
  }
  Dedup(&states);
  if (states.size() > 1) {
    // Multiple mode found.
    // TODO(yukawa): consider this case.
    return base_state;
  }
  if (states[0] == kDirect) {
    return StatePair(false, base_state.conversion_mode);
  }
  return StatePair(true, states[0]);
}

TipInputModeManager::Config::Config()
    : use_global_mode(false) {}

class TipInputModeManager::InternalState {
 public:
  InternalState()
      : use_global_mode(false) {}
  bool use_global_mode;
  StatePair mozc_state;
  StatePair tsf_state;
  IndicatorVisibilityTracker indicator_visibility_tracker;
  vector<InputScope> input_scope;
};

// For Mode Indicator.
TipInputModeManager::Action TipInputModeManager::OnDissociateContext() {
  const IndicatorVisibilityTracker::Action action =
      state_->indicator_visibility_tracker.OnDissociateContext();
  switch (action) {
    case IndicatorVisibilityTracker::kUpdateUI:
      return kUpdateUI;
    default:
      return kDoNothing;
  }
}

TipInputModeManager::Action TipInputModeManager::OnTestKey(
    const VirtualKey &key, bool is_down, bool eaten) {
  const IndicatorVisibilityTracker::Action action =
      state_->indicator_visibility_tracker.OnTestKey(key, is_down, eaten);
  switch (action) {
    case IndicatorVisibilityTracker::kUpdateUI:
      return kUpdateUI;
    default:
      return kDoNothing;
  }
}

TipInputModeManager::Action TipInputModeManager::OnKey(
    const VirtualKey &key, bool is_down, bool eaten) {
  const IndicatorVisibilityTracker::Action action =
      state_->indicator_visibility_tracker.OnKey(key, is_down, eaten);
  switch (action) {
    case IndicatorVisibilityTracker::kUpdateUI:
      return kUpdateUI;
    default:
      return kDoNothing;
  }
}

TipInputModeManager::Action TipInputModeManager::OnMoveFocusedWindow() {
  const IndicatorVisibilityTracker::Action action =
      state_->indicator_visibility_tracker.OnMoveFocusedWindow();
  switch (action) {
    case IndicatorVisibilityTracker::kUpdateUI:
      return kUpdateUI;
    default:
      return kDoNothing;
  }
}

TipInputModeManager::TipInputModeManager(const Config &config)
    : state_(new InternalState) {
  state_->use_global_mode = config.use_global_mode;
}

TipInputModeManager::~TipInputModeManager() {}

TipInputModeManager::NotifyActionSet TipInputModeManager::OnReceiveCommand(
    bool mozc_open_close_mode,
    DWORD mozc_logical_mode,
    DWORD mozc_visible_mode) {
  const StatePair prev_tsf_state = state_->tsf_state;

  state_->tsf_state.open_close = mozc_open_close_mode;
  state_->tsf_state.conversion_mode =
      static_cast<ConversionMode>(mozc_logical_mode);
  state_->mozc_state.open_close = mozc_open_close_mode;
  state_->mozc_state.conversion_mode =
      static_cast<ConversionMode>(mozc_visible_mode);

  NotifyActionSet action_set = kNotifyNothing;
  if (prev_tsf_state.open_close != state_->tsf_state.open_close) {
    action_set |= kNotifySystemOpenClose;
  }
  if (prev_tsf_state.conversion_mode != state_->tsf_state.conversion_mode) {
    action_set |= kNotifySystemConversionMode;
  }
  if (action_set != kNotifyNothing) {
    state_->indicator_visibility_tracker.OnChangeInputMode();
  }
  return action_set;
}

void TipInputModeManager::OnInitialize(bool system_open_close_mode,
                                       DWORD system_conversion_mode) {
  state_->mozc_state.open_close = system_open_close_mode;
  state_->tsf_state.open_close = system_open_close_mode;
  if (state_->use_global_mode) {
    return;
  }
  CompositionMode mozc_mode = commands::HIRAGANA;
  if (ConversionModeUtil::ToMozcMode(system_conversion_mode, &mozc_mode)) {
    state_->tsf_state.conversion_mode =
        static_cast<ConversionMode>(mozc_mode);
  }
  state_->mozc_state.conversion_mode = state_->tsf_state.conversion_mode;
}

TipInputModeManager::Action TipInputModeManager::OnSetFocus(
    bool system_open_close_mode,
    DWORD system_conversion_mode,
    const vector<InputScope> &input_scopes) {
  const StatePair prev_effective = state_->mozc_state;

  state_->indicator_visibility_tracker.OnMoveFocusedWindow();

  vector<InputScope> new_input_scopes = input_scopes;
  Dedup(&new_input_scopes);

  state_->tsf_state.open_close = system_open_close_mode;
  CompositionMode mozc_mode = commands::HIRAGANA;
  if (!state_->use_global_mode) {
    if (ConversionModeUtil::ToMozcMode(system_conversion_mode, &mozc_mode)) {
      state_->tsf_state.conversion_mode =
          static_cast<ConversionMode>(mozc_mode);
    }
  }

  if (new_input_scopes.size() > 0 &&
      (new_input_scopes == state_->input_scope)) {
    // The same input scope is specified. Use the previous mode.
    return kDoNothing;
  }

  swap(state_->input_scope, new_input_scopes);
  state_->mozc_state = GetOverriddenState(state_->tsf_state, input_scopes);
  if ((state_->mozc_state.open_close != prev_effective.open_close) ||
      (state_->mozc_state.conversion_mode !=
       prev_effective.conversion_mode)) {
    state_->indicator_visibility_tracker.OnChangeInputMode();
    return kUpdateUI;
  }
  return kDoNothing;
}

TipInputModeManager::Action
TipInputModeManager::OnChangeOpenClose(bool new_open_close_mode) {
  const bool prev_open = state_->mozc_state.open_close;  // effective on/off

  state_->tsf_state.open_close = new_open_close_mode;
  if (prev_open != new_open_close_mode) {
    state_->mozc_state.open_close = new_open_close_mode;
    state_->indicator_visibility_tracker.OnChangeInputMode();
    return kUpdateUI;
  }
  return kDoNothing;
}

TipInputModeManager::Action
TipInputModeManager::OnChangeConversionMode(DWORD new_conversion_mode) {
  const StatePair prev_effective = state_->mozc_state;

  if (state_->use_global_mode) {
    // Ignore mode change.
    return kDoNothing;
  }

  CompositionMode mozc_mode = commands::HIRAGANA;
  if (ConversionModeUtil::ToMozcMode(new_conversion_mode, &mozc_mode)) {
    state_->tsf_state.conversion_mode =
        static_cast<ConversionMode>(mozc_mode);
    state_->mozc_state.conversion_mode =
        static_cast<ConversionMode>(mozc_mode);
  }

  if (prev_effective.conversion_mode !=
      state_->mozc_state.conversion_mode) {
    state_->indicator_visibility_tracker.OnChangeInputMode();
    return kUpdateUI;
  }
  return kDoNothing;
}

TipInputModeManager::Action
TipInputModeManager::OnChangeInputScope(
    const vector<InputScope> &input_scopes) {
  const StatePair prev_effective = state_->mozc_state;

  vector<InputScope> new_input_scopes = input_scopes;
  Dedup(&new_input_scopes);
  if (new_input_scopes == state_->input_scope) {
    // The same input scope is specified. Use the previous mode.
    return kDoNothing;
  }

  swap(state_->input_scope, new_input_scopes);
  state_->mozc_state = GetOverriddenState(state_->tsf_state, input_scopes);
  if ((state_->mozc_state.open_close != prev_effective.open_close) ||
      (state_->mozc_state.conversion_mode !=
       prev_effective.conversion_mode)) {
    state_->indicator_visibility_tracker.OnChangeInputMode();
    return kUpdateUI;
  }
  return kDoNothing;
}

bool TipInputModeManager::GetEffectiveOpenClose() const {
  return state_->mozc_state.open_close;
}

bool TipInputModeManager::GetTsfOpenClose() const {
  return state_->tsf_state.open_close;
}

TipInputModeManagerImpl::ConversionMode
TipInputModeManager::GetEffectiveConversionMode() const {
  return state_->mozc_state.conversion_mode;
}

TipInputModeManagerImpl::ConversionMode
TipInputModeManager::GetTsfConversionMode() const {
  return state_->tsf_state.conversion_mode;
}

bool TipInputModeManager::IsIndicatorVisible() const {
  return state_->indicator_visibility_tracker.IsVisible();
}

}  // namespace tsf
}  // namespace win32
}  // namespace mozc
