# -*- coding: utf-8 -*-
# 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.

"""Single kanji dictionary generator.

How to run this script:
gen_single_kanji_rewriter_data.py
  --single_kanji_file=single_kanji.tsv
  --variant_file=variant_rule.txt
  --output=single_kanji_data.h
"""

__author__ = "hidehiko"

import optparse
from build_tools import code_generator_util
from rewriter import embedded_dictionary_compiler

# key, value, rank
NOUN_PREFIX = [
    ['お', 'お', 1],
    ['ご', 'ご', 1],
    # ['ご', '誤'],    # don't register it as 誤 isn't in the ipadic.
    # ['み', 'み'],    # seems to be rare.
    ['もと', 'もと', 1],
    ['だい', '代', 1],
    ['てい', '低', 0],
    ['もと', '元', 1],
    ['ぜん', '全', 0],
    ['さい', '再', 0],
    ['しょ', '初', 1],
    ['はつ', '初', 0],
    ['ぜん', '前', 1],
    ['かく', '各', 1],
    ['どう', '同', 1],
    ['だい', '大', 1],
    ['おお', '大', 1],
    ['とう', '当', 1],
    ['ご', '御', 1],
    ['お', '御', 1],
    ['しん', '新', 1],
    ['さい', '最', 1],
    ['み', '未', 0],
    ['ほん', '本', 1],
    ['む', '無', 0],
    ['だい', '第', 1],
    ['とう', '等', 1],
    ['やく', '約', 1],
    ['ひ', '被', 1],
    ['ちょう', '超', 1],
    ['ちょう', '長', 1],
    ['なが', '長', 1],
    ['ひ', '非', 1],
    ['こう', '高', 1]
]


def ReadSingleKanji(stream):
  """Parses single kanji dictionary data from stream."""
  stream = code_generator_util.SkipLineComment(stream)
  stream = code_generator_util.ParseColumnStream(stream, num_column=2)
  outputs = list(stream)
  # For binary search by |key|, sort outputs here.
  outputs.sort(lambda x, y: cmp(x[0], y[0]))

  return outputs


def ReadVariant(stream):
  """Parses variant data from stream."""
  variant_types = []
  variant_items = []

  stream = code_generator_util.SkipLineComment(stream)
  stream = code_generator_util.ParseColumnStream(stream)
  for tokens in stream:
    if len(tokens) == 1:
      variant_types.append(tokens[0])
    elif len(tokens) == 2 and variant_types:
      (target, original) = tokens
      variant_items.append([target, original, len(variant_types) - 1])

  # For binary search by |target|, sort variant items here.
  variant_items.sort(lambda x, y: cmp(x[0], y[0]))

  return (variant_types, variant_items)


def GenNounPrefix():
  """Generates noun prefix embedded dictionary entries."""
  token_map = {}
  for entry in NOUN_PREFIX:
    key = entry[0] if entry[0] else None
    value = entry[1] if entry[1] else None
    rank = entry[2]

    token_map.setdefault(key, []).append(
        embedded_dictionary_compiler.Token(
            key, value, None, None, 0, 0, rank))

  return token_map


def WriteSingleKanji(outputs, stream):
  """Writes single kanji list for readings."""
  stream.write('static const SingleKanjiList kSingleKanjis[] = {\n')
  for output in outputs:
    (key, values) = output
    stream.write('  // %s, %s\n' % (key, values))
    stream.write(code_generator_util.FormatWithCppEscape(
        '  { %s, %s },\n', key, values))
  stream.write('};\n')


def WriteVariantInfo(variant_info, stream):
  """Writes single kanji variants info."""
  (variant_types, variant_items) = variant_info

  stream.write('static const char *kKanjiVariantTypes[] = {\n')
  for variant_type in variant_types:
    stream.write(code_generator_util.FormatWithCppEscape(
        '  %s,', variant_type))
    stream.write('  // %s\n' % variant_type)
  stream.write('};\n')

  stream.write('static const KanjiVariantItem kKanjiVariants[] = {\n')
  for item in variant_items:
    (target, original, variant_type) = item
    stream.write(code_generator_util.FormatWithCppEscape(
        '  { %s, %s, %d },', target, original, variant_type))
    stream.write('  // %s, %s, %d\n' % (target, original, variant_type))
  stream.write('};\n')


def _ParseOptions():
  parser = optparse.OptionParser()

  parser.add_option('--single_kanji_file', dest='single_kanji_file',
                    help='Single kanji file')
  parser.add_option('--variant_file', dest='variant_file',
                    help='Variant rule file')
  parser.add_option('--output', dest='output', help='Output header file.')

  return parser.parse_args()[0]


def main():
  options = _ParseOptions()

  with open(options.single_kanji_file, 'r') as single_kanji_stream:
    single_kanji = ReadSingleKanji(single_kanji_stream)

  with open(options.variant_file, 'r') as variant_stream:
    variant_info = ReadVariant(variant_stream)

  noun_prefix = GenNounPrefix()

  with open(options.output, 'w') as output_stream:
    WriteSingleKanji(single_kanji, output_stream)
    WriteVariantInfo(variant_info, output_stream)
    embedded_dictionary_compiler.Compile(
        'NounPrefixData', noun_prefix, output_stream)


if __name__ == '__main__':
  main()
