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

package org.mozc.android.inputmethod.japanese.model;

import org.mozc.android.inputmethod.japanese.EmoticonData;
import org.mozc.android.inputmethod.japanese.SymbolData;
import org.mozc.android.inputmethod.japanese.emoji.EmojiData;
import org.mozc.android.inputmethod.japanese.emoji.EmojiProviderType;
import org.mozc.android.inputmethod.japanese.emoji.EmojiUtil;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCandidates.Annotation;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCandidates.CandidateList;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCandidates.CandidateWord;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Manages between MinorCategory and its candidates.
 *
 */
public class SymbolCandidateStorage {

  /** Interface to handle symbol history data. */
  public interface SymbolHistoryStorage {
    public List<String> getAllHistory(SymbolMajorCategory majorCategory);
    public void addHistory(SymbolMajorCategory majorCategory, String value);
  }

  /** Set of names of Emoji based on carriers. */
  private static class EmojiDescriptionSet {
    static final EmojiDescriptionSet NULL_INSTANCE;
    static {
        String[] empty = new String[0];
        NULL_INSTANCE = new EmojiDescriptionSet(empty, empty, empty, empty, empty);
    }

    final String[] faceDescription;
    final String[] foodDescription;
    final String[] activityDescription;
    final String[] cityDescription;
    final String[] natureDescription;

    EmojiDescriptionSet(String[] faceDescription,
                        String[] foodDescription,
                        String[] activityDescription,
                        String[] cityDescription,
                        String[] natureDescription) {
      this.faceDescription = Preconditions.checkNotNull(faceDescription);
      this.foodDescription = Preconditions.checkNotNull(foodDescription);
      this.activityDescription = Preconditions.checkNotNull(activityDescription);
      this.cityDescription = Preconditions.checkNotNull(cityDescription);
      this.natureDescription = Preconditions.checkNotNull(natureDescription);
    }
  }

  /** Annotation for a Half-width one character candidate. */
  private static final String HALFWIDTH_DESCRIPTION = "[半]";
  private static final Annotation HALFWIDTH_ANNOTATION = Annotation.newBuilder()
      .setDescription(HALFWIDTH_DESCRIPTION)
      .build();

  /** Specialized description map. */
  private static final Map<String, String> DESCRIPTION_MAP;
  static {
    // TODO(team): Move this rules compile time generated code, rather than hard coding here.
    Map<String, String> descriptionMap = new HashMap<String, String>();
    descriptionMap.put("\u0020", "半角ｽﾍﾟｰｽ");  // (space)
    descriptionMap.put("\u002d", "[半]ﾊｲﾌﾝ,ﾏｲﾅｽ");  // -
    descriptionMap.put("\u2010", "[全]ﾊｲﾌﾝ");  // ‐
    descriptionMap.put("\u2015", "[全]ﾀﾞｯｼｭ");  // ―
    descriptionMap.put("\u2212", "[全]ﾏｲﾅｽ");  // −
    descriptionMap.put("\u3000", "全角ｽﾍﾟｰｽ"); // (space)
    descriptionMap.put("\uDBBA\uDF4C", "全部ﾌﾞﾗﾝｸ");  // Full-width space emoji.
    descriptionMap.put("\uDBBA\uDF4D", "半分ﾌﾞﾗﾝｸ");  // Half-width space emoji.
    descriptionMap.put("\uDBBA\uDF4E", "1/4ﾌﾞﾗﾝｸ");  // Quater-width space emoji.

    DESCRIPTION_MAP = Collections.unmodifiableMap(descriptionMap);
  }

  /** Map from the carrier to its Emoji description set. */
  private static final Map<EmojiProviderType, EmojiDescriptionSet>
      CARRIER_EMOJI_DESCRIPTION_SET_MAP;
  static {
    EnumMap<EmojiProviderType, EmojiDescriptionSet> map =
        new EnumMap<EmojiProviderType, EmojiDescriptionSet>(EmojiProviderType.class);
    map.put(EmojiProviderType.DOCOMO,
            new EmojiDescriptionSet(EmojiData.DOCOMO_FACE_NAME,
                                    EmojiData.DOCOMO_FOOD_NAME,
                                    EmojiData.DOCOMO_ACTIVITY_NAME,
                                    EmojiData.DOCOMO_CITY_NAME,
                                    EmojiData.DOCOMO_NATURE_NAME));
    map.put(EmojiProviderType.SOFTBANK,
            new EmojiDescriptionSet(EmojiData.SOFTBANK_FACE_NAME,
                                    EmojiData.SOFTBANK_FOOD_NAME,
                                    EmojiData.SOFTBANK_ACTIVITY_NAME,
                                    EmojiData.SOFTBANK_CITY_NAME,
                                    EmojiData.SOFTBANK_NATURE_NAME));
    map.put(EmojiProviderType.KDDI,
            new EmojiDescriptionSet(EmojiData.KDDI_FACE_NAME,
                                    EmojiData.KDDI_FOOD_NAME,
                                    EmojiData.KDDI_ACTIVITY_NAME,
                                    EmojiData.KDDI_CITY_NAME,
                                    EmojiData.KDDI_NATURE_NAME));
    CARRIER_EMOJI_DESCRIPTION_SET_MAP = Collections.unmodifiableMap(map);
  }

  private final SymbolHistoryStorage symbolHistoryStorage;
  private boolean isUnicodeEmojiEnabled = false;
  private boolean isCarrierEmojiEnabled = false;
  private EmojiProviderType emojiProviderType = EmojiProviderType.NONE;
  private EmojiDescriptionSet carrierEmojiDescriptionSet = EmojiDescriptionSet.NULL_INSTANCE;
  private Map<String, String> emojiDescriptionMap = Collections.emptyMap();

  public SymbolCandidateStorage(SymbolHistoryStorage symbolHistoryStorage) {
    this.symbolHistoryStorage = Preconditions.checkNotNull(symbolHistoryStorage);
    setEmojiProviderTypeInternal(EmojiProviderType.NONE);
  }

  public void setEmojiEnabled(boolean isUnicodeEmojiEnabled, boolean isCarrierEmojiEnabled) {
    this.isUnicodeEmojiEnabled = isUnicodeEmojiEnabled;
    this.isCarrierEmojiEnabled = isCarrierEmojiEnabled;
  }

  public void setEmojiProviderType(EmojiProviderType emojiProviderType) {
    if (this.emojiProviderType == Preconditions.checkNotNull(emojiProviderType)) {
      // No change.
      return;
    }
    setEmojiProviderTypeInternal(emojiProviderType);
  }

  private void setEmojiProviderTypeInternal(EmojiProviderType emojiProviderType) {
    EmojiDescriptionSet carrierEmojiDescriptionSet =
        CARRIER_EMOJI_DESCRIPTION_SET_MAP.get(emojiProviderType);
    this.emojiProviderType = emojiProviderType;
    if (carrierEmojiDescriptionSet == null) {
      this.carrierEmojiDescriptionSet = EmojiDescriptionSet.NULL_INSTANCE;
      this.emojiDescriptionMap = createEmojiDescriptionMap(Optional.<EmojiDescriptionSet>absent());
    } else {
      this.carrierEmojiDescriptionSet = carrierEmojiDescriptionSet;
      this.emojiDescriptionMap = createEmojiDescriptionMap(Optional.of(carrierEmojiDescriptionSet));
    }
  }

  private static Map<String, String> createEmojiDescriptionMap(
      Optional<EmojiDescriptionSet> carrierEmojiDescriptionSet) {
    Preconditions.checkNotNull(carrierEmojiDescriptionSet);

    Map<String, String> map = new HashMap<String, String>();

    createEmojiDescriptionMapInternal(
        EmojiData.FACE_VALUES, EmojiData.UNICODE_FACE_NAME, map);
    createEmojiDescriptionMapInternal(
        EmojiData.FOOD_VALUES, EmojiData.UNICODE_FOOD_NAME, map);
    createEmojiDescriptionMapInternal(
        EmojiData.ACTIVITY_VALUES, EmojiData.UNICODE_ACTIVITY_NAME, map);
    createEmojiDescriptionMapInternal(
        EmojiData.CITY_VALUES, EmojiData.UNICODE_CITY_NAME, map);
    createEmojiDescriptionMapInternal(
        EmojiData.NATURE_VALUES, EmojiData.UNICODE_NATURE_NAME, map);

    if (carrierEmojiDescriptionSet.isPresent()) {
      EmojiDescriptionSet descriptionSet = carrierEmojiDescriptionSet.get();
      createEmojiDescriptionMapInternal(
          EmojiData.FACE_PUA_VALUES, descriptionSet.faceDescription, map);
      createEmojiDescriptionMapInternal(
          EmojiData.FOOD_PUA_VALUES, descriptionSet.foodDescription, map);
      createEmojiDescriptionMapInternal(
          EmojiData.ACTIVITY_PUA_VALUES, descriptionSet.activityDescription, map);
      createEmojiDescriptionMapInternal(
          EmojiData.CITY_PUA_VALUES, descriptionSet.cityDescription, map);
      createEmojiDescriptionMapInternal(
          EmojiData.NATURE_PUA_VALUES, descriptionSet.natureDescription, map);
    }

    return Collections.unmodifiableMap(map);
  }

  private static void createEmojiDescriptionMapInternal(
      String[] values, String[] descriptions, Map<String, String> map) {
    Preconditions.checkArgument(values.length == descriptions.length);

    for (int i = 0; i < descriptions.length; ++i) {
      String description = descriptions[i];
      if (description != null) {
        map.put(values[i], description);
      }
    }
  }

  /** @return the {@link CandidateList} instance for the given {@code minorCategory}. */
  public CandidateList getCandidateList(SymbolMinorCategory minorCategory) {
    switch (minorCategory) {
      // NUMBER major category candidates.
      case NUMBER:
        return CandidateList.getDefaultInstance();

      // SYMBOL major category candidates.
      case SYMBOL_HISTORY:
        return toCandidateList(symbolHistoryStorage.getAllHistory(SymbolMajorCategory.SYMBOL));
      case SYMBOL_GENERAL:
        return toCandidateList(Arrays.asList(SymbolData.GENERAL_VALUES));
      case SYMBOL_HALF:
        return toCandidateList(Arrays.asList(SymbolData.HALF_VALUES));
      case SYMBOL_PARENTHESIS:
        return toCandidateList(Arrays.asList(SymbolData.PARENTHESIS_VALUES));
      case SYMBOL_ARROW:
        return toCandidateList(Arrays.asList(SymbolData.ARROW_VALUES));
      case SYMBOL_MATH:
        return toCandidateList(Arrays.asList(SymbolData.MATH_VALUES));

      // EMOTICON major category candidates.
      case EMOTICON_HISTORY:
        return toCandidateList(symbolHistoryStorage.getAllHistory(SymbolMajorCategory.EMOTICON));
      case EMOTICON_SMILE:
        return toCandidateList(Arrays.asList(EmoticonData.SMILE_VALUES));
      case EMOTICON_SWEAT:
        return toCandidateList(Arrays.asList(EmoticonData.SWEAT_VALUES));
      case EMOTICON_SURPRISE:
        return toCandidateList(Arrays.asList(EmoticonData.SURPRISE_VALUES));
      case EMOTICON_SADNESS:
        return toCandidateList(Arrays.asList(EmoticonData.SADNESS_VALUES));
      case EMOTICON_DISPLEASURE:
        return toCandidateList(Arrays.asList(EmoticonData.DISPLEASURE_VALUES));

      // EMOJI major category candidates.
      case EMOJI_HISTORY:
        return toEmojiCandidateListForHistory(
            symbolHistoryStorage.getAllHistory(SymbolMajorCategory.EMOJI),
            emojiDescriptionMap, isCarrierEmojiEnabled);
      case EMOJI_FACE:
        return toEmojiCandidateList(
            EmojiData.FACE_VALUES, EmojiData.UNICODE_FACE_NAME,
            EmojiData.FACE_PUA_VALUES, carrierEmojiDescriptionSet.faceDescription,
            isUnicodeEmojiEnabled, isCarrierEmojiEnabled);
      case EMOJI_FOOD:
        return toEmojiCandidateList(
            EmojiData.FOOD_VALUES, EmojiData.UNICODE_FOOD_NAME,
            EmojiData.FOOD_PUA_VALUES, carrierEmojiDescriptionSet.foodDescription,
            isUnicodeEmojiEnabled, isCarrierEmojiEnabled);
      case EMOJI_ACTIVITY:
        return toEmojiCandidateList(
            EmojiData.ACTIVITY_VALUES, EmojiData.UNICODE_ACTIVITY_NAME,
            EmojiData.ACTIVITY_PUA_VALUES, carrierEmojiDescriptionSet.activityDescription,
            isUnicodeEmojiEnabled, isCarrierEmojiEnabled);
      case EMOJI_CITY:
        return toEmojiCandidateList(
            EmojiData.CITY_VALUES, EmojiData.UNICODE_CITY_NAME,
            EmojiData.CITY_PUA_VALUES, carrierEmojiDescriptionSet.cityDescription,
            isUnicodeEmojiEnabled, isCarrierEmojiEnabled);
      case EMOJI_NATURE:
        return toEmojiCandidateList(
            EmojiData.NATURE_VALUES, EmojiData.UNICODE_NATURE_NAME,
            EmojiData.NATURE_PUA_VALUES, carrierEmojiDescriptionSet.natureDescription,
            isUnicodeEmojiEnabled, isCarrierEmojiEnabled);
    }

    throw new IllegalArgumentException("Unknown minor category: " + minorCategory.toString());
  }

  /** Just short cut of {@code toCandidateList(values, null)}. */
  private static CandidateList toCandidateList(List<String> values) {
    return toCandidateList(values, Optional.<Map<String, String>>absent());
  }

  /**
   * Builds the {@link CandidateList} based on the given values and emojiDescriptionMap.
   *
   * If {@code isCarrierEmojiEnabled} is {@code false}, this method ignores carrier emoji not to
   * allow users to input it on the focused text edit. Otherwise some application
   * (e.g. GoogleQuickSearchBox) crashes when they receives carrier emoji.
   */
  private static CandidateList toEmojiCandidateListForHistory(
      List<String> values, Map<String, String> emojiDescriptionMap, boolean isCarrierEmojiEnabled) {
    if (isCarrierEmojiEnabled) {
      return toCandidateList(values, Optional.of(emojiDescriptionMap));
    }

    List<String> valuesWithoutCarrierEmoji = new ArrayList<String>(values.size());
    for (String value : values) {
      if (value.codePointCount(0, value.length()) != 1 ||
          !EmojiUtil.isCarrierEmoji(value.codePointAt(0))) {
        valuesWithoutCarrierEmoji.add(value);
      }
    }
    return toCandidateList(valuesWithoutCarrierEmoji, Optional.of(emojiDescriptionMap));
  }

  /** Builds the {@link CandidateList} based on the given values and emojiDescriptionMap. */
  @VisibleForTesting
  static CandidateList toCandidateList(
      List<String> values, Optional<Map<String, String>> emojiDescriptionMap) {
    Preconditions.checkNotNull(emojiDescriptionMap);
    if (Preconditions.checkNotNull(values).isEmpty()) {
      return CandidateList.getDefaultInstance();
    }

    CandidateList.Builder builder = CandidateList.newBuilder();
    int index = 0;
    for (String value : values) {
      CandidateWord.Builder wordBuilder = CandidateWord.newBuilder();
      wordBuilder.setValue(value);
      wordBuilder.setId(index);
      wordBuilder.setIndex(index);
      Optional<Annotation> annotation = getAnnotation(value, emojiDescriptionMap);
      if (annotation.isPresent()) {
        wordBuilder.setAnnotation(annotation.get());
      }
      builder.addCandidates(wordBuilder);
      ++index;
    }
    return builder.build();
  }

  private static Optional<Annotation> getAnnotation(
      String value, Optional<Map<String, String>> emojiDescriptionMap) {
    // We do not use resource to store the string below because
    // there are no needs to translate the description.
    // In addition we cannot access the resource from here
    // because Context is not available.

    // Rule base annotation.
    {
      String description = DESCRIPTION_MAP.get(value);
      if (description != null) {
        return Optional.of(Annotation.newBuilder().setDescription(description).build());
      }
    }

    // Emoji specialized annotation. Note that the given map depends on the current provider type.
    // This is just only for history annotation.
    if (emojiDescriptionMap.isPresent()){
      String description = emojiDescriptionMap.get().get(value);
      if (description != null) {
        return Optional.of(Annotation.newBuilder().setDescription(description).build());
      }
    }

    // If the candidate has only one character and its codepoint is <= 0x7F,
    // add HALFWIDTH_ANNOTATION.
    // This criteria is different from the Mozc engine's
    // (it is basically the same as here but length check is omitted)
    // but the engine's criteria seems too aggressive for our purpose.
    if (value.length() == 1 && value.charAt(0) <= 0x7F) {
      return Optional.of(HALFWIDTH_ANNOTATION);
    }

    // No description is available.
    return Optional.absent();
  }

  private static CandidateList toEmojiCandidateList(
      String[] unicodeEmojiValues, String[] unicodeEmojiDescriptions,
      String[] carrierEmojiValues, String[] carrierEmojiDescriptions,
      boolean isUnicodeEmojiEnabled, boolean isCarrierEmojiEnabled) {
    CandidateList.Builder builder = CandidateList.newBuilder();
    int index = 0;

    if (isUnicodeEmojiEnabled) {
      index += addEmojiCandidateListToBuilder(
          builder, index, unicodeEmojiValues, unicodeEmojiDescriptions);
    }
    if (isCarrierEmojiEnabled) {
      index += addEmojiCandidateListToBuilder(
          builder, index, carrierEmojiValues, carrierEmojiDescriptions);
    }

    if (index == 0) {
      // No values are available.
      return CandidateList.getDefaultInstance();
    }
    return builder.build();
  }

  /** @return The number of added candidates. */
  private static int addEmojiCandidateListToBuilder(
      CandidateList.Builder builder, int startIndex, String[] values, String[] descriptions) {
    int index = startIndex;
    for (int i = 0; i < descriptions.length; ++i) {
      String description = descriptions[i];
      if (description == null) {
        // If no description (name) is available, we skip the value,
        // because the value is not supported under the current carrier.
        continue;
      }

      builder.addCandidates(CandidateWord.newBuilder()
          .setValue(values[i])
          .setId(index)
          .setIndex(index)
          .setAnnotation(Annotation.newBuilder()
              .setDescription(description)));
      ++index;
    }
    return index - startIndex;
  }
}
