// 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 "rewriter/calculator_rewriter.h"

#include <algorithm>
#include <string>

#include "base/logging.h"
#include "base/util.h"
#include "config/config.pb.h"
#include "config/config_handler.h"
#include "converter/conversion_request.h"
#include "converter/converter_interface.h"
#include "converter/segments.h"
#include "rewriter/calculator/calculator_interface.h"
#include "session/commands.pb.h"

namespace mozc {

CalculatorRewriter::CalculatorRewriter(
    const ConverterInterface *parent_converter)
    : parent_converter_(parent_converter) {
  DCHECK(parent_converter_);
}

CalculatorRewriter::~CalculatorRewriter() {}

int CalculatorRewriter::capability(const ConversionRequest &request) const {
  if (request.request().mixed_conversion()) {
    return RewriterInterface::ALL;
  }
  return RewriterInterface::CONVERSION;
}

// Rewrites candidates when conversion segments of |segments| represents an
// expression that can be calculated. In such case, if |segments| consists
// of multiple segments, it merges them by calling ConverterInterface::
// ResizeSegment(), otherwise do calculation and insertion.
// TODO(tok): It currently calculates same expression twice, if |segments| is
//            a valid expression.
bool CalculatorRewriter::Rewrite(const ConversionRequest &request,
                                 Segments *segments) const {
  if (!GET_CONFIG(use_calculator)) {
    return false;
  }

  CalculatorInterface *calculator = CalculatorFactory::GetCalculator();

  const size_t segments_size = segments->conversion_segments_size();
  if (segments_size == 0) {
    return false;
  }

  // If |segments| has only one conversion segment, try calculation and insert
  // the result on success.
  if (segments_size == 1) {
    const string &key = segments->conversion_segment(0).key();
    string result;
    if (key.empty()) {
      return false;
    }
    if (!calculator->CalculateString(key, &result)) {
      return false;
    }
    // Insert the result.
    if (!InsertCandidate(result, 0, segments->mutable_conversion_segment(0))) {
      return false;
    }
    return true;
  }

  // Merge keys of all conversion segments and try calculation.
  string merged_key;
  for (size_t i = 0; i < segments->conversion_segments_size(); ++i) {
    merged_key += segments->conversion_segment(i).key();
  }
  // The decision to calculate and calculation itself are both done by the
  // calculator.
  string result;
  if (!calculator->CalculateString(merged_key, &result)) {
    return false;
  }

  // Merge all conversion segments.
  int offset = Util::CharsLen(merged_key) -
                   Util::CharsLen(segments->conversion_segment(0).key());
  // ConverterInterface::ResizeSegment() calls Rewriter::Rewrite(), so
  // CalculatorRewriter::Rewrite() is recursively called with merged
  // conversion segment.
  if (!parent_converter_->ResizeSegment(segments, request, 0, offset)) {
    LOG(ERROR) << "Failed to merge conversion segments";
    return false;
  }
  return true;
}

bool CalculatorRewriter::InsertCandidate(const string &value,
                                         size_t insert_pos,
                                         Segment *segment) const {
  if (segment->candidates_size() == 0) {
    LOG(WARNING) << "candidates_size is 0";
    return false;
  }

  const Segment::Candidate &base_candidate = segment->candidate(0);

  // Normalize the expression, used in description.
  string temp, temp2, expression;
  Util::FullWidthAsciiToHalfWidthAscii(base_candidate.content_key, &temp);
  // "・"
  Util::StringReplace(temp, "\xE3\x83\xBB", "/", true, &temp2);
  // "ー", onbiki
  Util::StringReplace(temp2, "\xE3\x83\xBC", "-", true, &expression);

  size_t offset = min(insert_pos, segment->candidates_size());

  for (int n = 0; n < 2; ++n) {
    int current_offset = offset + n;
    Segment::Candidate *candidate = segment->insert_candidate(
        current_offset);
    if (candidate == NULL) {
      LOG(ERROR) << "cannot insert candidate at " << current_offset;
      return false;
    }

    // Simply sets some member variables of the new candidate to ones of the
    // existing candidate next to it.
    size_t reference_index = current_offset + 1;
    if (reference_index >= segment->candidates_size()) {
      reference_index = current_offset - 1;
    }
    const Segment::Candidate &reference_candidate =
        segment->candidate(reference_index);

    candidate->Init();
    candidate->lid = reference_candidate.lid;
    candidate->rid = reference_candidate.rid;
    candidate->cost = reference_candidate.cost;
    candidate->key = base_candidate.key;
    candidate->content_key = base_candidate.content_key;
    candidate->attributes |= Segment::Candidate::NO_VARIANTS_EXPANSION;
    candidate->attributes |= Segment::Candidate::NO_LEARNING;
    // "計算結果"
    candidate->description = "\xE8\xA8\x88\xE7\xAE\x97\xE7\xB5\x90\xE6\x9E\x9C";

    if (n == 0) {   // without expression
      candidate->value = value;
      candidate->content_value = value;
    } else {       // with expression
      candidate->value = expression + value;
      candidate->content_value = expression + value;
    }
  }

  return true;
}
}  // namespace mozc
