// 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"

namespace mozc {

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

CalculatorRewriter::~CalculatorRewriter() {}

// 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 (!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;
    // description "[expression] の計算結果"
    candidate->description = expression +
        " \xE3\x81\xAE\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
