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

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

import org.mozc.android.inputmethod.japanese.keyboard.BackgroundDrawableFactory.DrawableType;
import org.mozc.android.inputmethod.japanese.keyboard.Key.Stick;
import org.mozc.android.inputmethod.japanese.resources.R;
import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.util.DisplayMetrics;
import android.util.TypedValue;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 */
public class KeyboardParser {

  /** Attributes for the key dimensions. */
  private static class KeyAttributes {
    final int width;
    final int height;
    final int horizontalGap;
    final int verticalGap;
    DrawableType keyBackgroundDrawableType;

    KeyAttributes(int width, int height, int horizontalGap, int verticalGap,
                 DrawableType keyBackgroundDrawableType) {
      this.width = width;
      this.height = height;
      this.horizontalGap = horizontalGap;
      this.verticalGap = verticalGap;
      this.keyBackgroundDrawableType = keyBackgroundDrawableType;
    }
  }

  /** Attributes for the popup dimensions. */
  private static class PopUpAttributes {
    final int popUpWidth;
    final int popUpHeight;
    final int popUpXOffset;
    final int popUpYOffset;

    PopUpAttributes(int popUpWidth, int popUpHeight, int popUpXOffset, int popUpYOffset) {
      this.popUpWidth = popUpWidth;
      this.popUpHeight = popUpHeight;
      this.popUpXOffset = popUpXOffset;
      this.popUpYOffset = popUpYOffset;
    }
  }

  /*
   * Following codes are the list of attributes which a particular element can be support.
   * Note that, although it seems undocumented, the order of values in int[] attributes array
   * needs to be sorted. Considering the maintenance, we list attributes as we like,
   * sort in static block, and initialize the XXX_INDEX by binarySearch the value,
   * to keep the correct behavior regardless of editing the attr.xml file in future.
   */

  /** The attributes for a {@code <Row>} element. */
  private static final int[] ROW_ATTRIBUTES = {
    R.attr.verticalGap,
    R.attr.keyHeight,
    R.attr.rowEdgeFlags,
  };
  static {
    Arrays.sort(ROW_ATTRIBUTES);
  }
  private static final int ROW_VERTICAL_GAP_INDEX =
      Arrays.binarySearch(ROW_ATTRIBUTES, R.attr.verticalGap);
  private static final int ROW_KEY_HEIGHT_INDEX =
      Arrays.binarySearch(ROW_ATTRIBUTES, R.attr.keyHeight);
  private static final int ROW_ROW_EDGE_FLAGS_INDEX =
      Arrays.binarySearch(ROW_ATTRIBUTES, R.attr.rowEdgeFlags);

  /** Attributes for a {@code <Key>} element. */
  private static final int[] KEY_ATTRIBUTES = {
    R.attr.keyWidth,
    R.attr.keyHeight,
    R.attr.horizontalGap,
    R.attr.keyBackground,
    R.attr.keyEdgeFlags,
    R.attr.isRepeatable,
    R.attr.isModifier,
    R.attr.isSticky,
  };
  static {
    Arrays.sort(KEY_ATTRIBUTES);
  }
  private static final int KEY_KEY_WIDTH_INDEX =
      Arrays.binarySearch(KEY_ATTRIBUTES, R.attr.keyWidth);
  private static final int KEY_KEY_HEIGHT_INDEX =
      Arrays.binarySearch(KEY_ATTRIBUTES, R.attr.keyHeight);
  private static final int KEY_HORIZONTAL_GAP_INDEX =
      Arrays.binarySearch(KEY_ATTRIBUTES, R.attr.horizontalGap);
  private static final int KEY_KEY_BACKGROUND_INDEX =
      Arrays.binarySearch(KEY_ATTRIBUTES, R.attr.keyBackground);
  private static final int KEY_KEY_EDGE_FLAGS_INDEX =
      Arrays.binarySearch(KEY_ATTRIBUTES, R.attr.keyEdgeFlags);
  private static final int KEY_IS_REPEATABLE_INDEX =
      Arrays.binarySearch(KEY_ATTRIBUTES, R.attr.isRepeatable);
  private static final int KEY_IS_MODIFIER_INDEX =
      Arrays.binarySearch(KEY_ATTRIBUTES, R.attr.isModifier);
  private static final int KEY_IS_STICKY_INDEX =
      Arrays.binarySearch(KEY_ATTRIBUTES, R.attr.isSticky);

  /** Attributes for a {@code <Spacer>} element. */
  private static final int[] SPACER_ATTRIBUTES = {
    R.attr.keyHeight,
    R.attr.horizontalGap,
    R.attr.keyEdgeFlags,
    R.attr.stick,
  };
  static {
    Arrays.sort(SPACER_ATTRIBUTES);
  }
  private static final int SPACER_KEY_HEIGHT_INDEX =
      Arrays.binarySearch(SPACER_ATTRIBUTES, R.attr.keyHeight);
  private static final int SPACER_HORIZONTAL_GAP_INDEX =
      Arrays.binarySearch(SPACER_ATTRIBUTES, R.attr.horizontalGap);
  private static final int SPACER_KEY_EDGE_FLAGS_INDEX =
      Arrays.binarySearch(SPACER_ATTRIBUTES, R.attr.keyEdgeFlags);
  private static final int SPACER_STICK_INDEX =
      Arrays.binarySearch(SPACER_ATTRIBUTES, R.attr.stick);

  /** Attributes for a {@code <KeyState>} element. */
  private static final int[] KEY_STATE_ATTRIBUTES = {
    R.attr.contentDescription,
    R.attr.keyBackground,
    R.attr.metaState,
    R.attr.nextMetaState,
    R.attr.nextRemovedMetaStates,
  };
  static {
    Arrays.sort(KEY_STATE_ATTRIBUTES);
  }
  private static final int KEY_STATE_CONTENT_DESCRIPTION_INDEX =
      Arrays.binarySearch(KEY_STATE_ATTRIBUTES, R.attr.contentDescription);
  private static final int KEY_STATE_KEY_BACKGROUND_INDEX =
      Arrays.binarySearch(KEY_STATE_ATTRIBUTES, R.attr.keyBackground);
  private static final int KEY_STATE_META_STATE_INDEX =
      Arrays.binarySearch(KEY_STATE_ATTRIBUTES, R.attr.metaState);
  private static final int KEY_STATE_NEXT_META_STATE_INDEX =
      Arrays.binarySearch(KEY_STATE_ATTRIBUTES, R.attr.nextMetaState);
  private static final int KEY_STATE_NEXT_REMOVED_META_STATES_INDEX =
      Arrays.binarySearch(KEY_STATE_ATTRIBUTES, R.attr.nextRemovedMetaStates);

  /** Attributes for a {@code <KeyEntity>} element. */
  private static final int[] KEY_ENTITY_ATTRIBUTES = {
    R.attr.sourceId,
    R.attr.keyCode,
    R.attr.longPressKeyCode,
    R.attr.keyIcon,
    R.attr.keyCharacter,
    R.attr.flickHighlight,
  };
  static {
    Arrays.sort(KEY_ENTITY_ATTRIBUTES);
  }
  private static final int KEY_ENTITY_SOURCE_ID_INDEX =
      Arrays.binarySearch(KEY_ENTITY_ATTRIBUTES, R.attr.sourceId);
  private static final int KEY_ENTITY_KEY_CODE_INDEX =
      Arrays.binarySearch(KEY_ENTITY_ATTRIBUTES, R.attr.keyCode);
  private static final int KEY_ENTITY_LONG_PRESS_KEY_CODE_INDEX =
      Arrays.binarySearch(KEY_ENTITY_ATTRIBUTES, R.attr.longPressKeyCode);
  private static final int KEY_ENTITY_KEY_ICON_INDEX =
      Arrays.binarySearch(KEY_ENTITY_ATTRIBUTES, R.attr.keyIcon);
  private static final int KEY_ENTITY_KEY_CHAR_INDEX =
      Arrays.binarySearch(KEY_ENTITY_ATTRIBUTES, R.attr.keyCharacter);
  private static final int KEY_ENTITY_FLICK_HIGHLIGHT_INDEX =
      Arrays.binarySearch(KEY_ENTITY_ATTRIBUTES, R.attr.flickHighlight);

  /**
   * Mapping table from enum value in xml to DrawableType by using the enum value as index.
   */
  private static final DrawableType[] KEY_BACKGROUND_DRAWABLE_TYPE_MAP = {
    DrawableType.TWELVEKEYS_REGULAR_KEY_BACKGROUND,
    DrawableType.TWELVEKEYS_FUNCTION_KEY_BACKGROUND,
    DrawableType.TWELVEKEYS_FUNCTION_KEY_BACKGROUND_WITH_THREEDOTS,
    DrawableType.QWERTY_REGULAR_KEY_BACKGROUND,
    DrawableType.QWERTY_FUNCTION_KEY_BACKGROUND,
    DrawableType.QWERTY_FUNCTION_KEY_BACKGROUND_WITH_THREEDOTS,
    DrawableType.QWERTY_FUNCTION_KEY_LIGHT_ON_BACKGROUND,
    DrawableType.QWERTY_FUNCTION_KEY_LIGHT_OFF_BACKGROUND,
  };

  /**
   * @return "sourceId" assigned to {@code value}.
   */
  static int getSourceId(TypedValue value, @SuppressWarnings("unused") int defaultValue) {
    if (value == null ||
        (value.type != TypedValue.TYPE_INT_DEC &&
         value.type != TypedValue.TYPE_INT_HEX)) {
      throw new IllegalArgumentException("sourceId is mandatory for KeyEntity.");
    }
    return value.data;
  }

  /**
   * @return the pixel offsets based on metrics and base
   */
  static int getDimensionOrFraction(
      TypedValue value, int base, int defaultValue, DisplayMetrics metrics) {
    if (value == null) {
      return defaultValue;
    }

    switch (value.type) {
      case TypedValue.TYPE_DIMENSION:
        return TypedValue.complexToDimensionPixelOffset(value.data, metrics);
      case TypedValue.TYPE_FRACTION:
        return Math.round(TypedValue.complexToFraction(value.data, base, base));
    }

    throw new IllegalArgumentException("The type dimension or fraction is required." +
                                       "  value = " + value.toString());
  }

  /**
   * @return "codes" assigned to {@code value}
   */
  static int getCode(TypedValue value, int defaultValue) {
    if (value == null) {
      return defaultValue;
    }

    if (value.type == TypedValue.TYPE_INT_DEC ||
        value.type == TypedValue.TYPE_INT_HEX) {
      return value.data;
    }
    if (value.type == TypedValue.TYPE_STRING) {
      return Integer.parseInt(value.string.toString());
    }

    return defaultValue;
  }

  /**
   * A simple wrapper of {@link CharSequence#toString()}, in order to avoid
   * {@code NullPointerException}.
   * @param sequence input character sequence
   * @return {@code sequence.toString()} if {@code sequence} is not {@code null}.
   *         Otherwise, {@code null}.
   */
  static String toStringOrNull(CharSequence sequence) {
    if (sequence == null) {
      return null;
    }
    return sequence.toString();
  }

  private static void ignoreWhiteSpaceAndComment(XmlPullParser parser)
      throws XmlPullParserException, IOException {
    int event = parser.getEventType();
    while (event == XmlPullParser.IGNORABLE_WHITESPACE || event == XmlPullParser.COMMENT) {
      event = parser.next();
    }
  }

  private static void assertStartDocument(XmlPullParser parser) throws XmlPullParserException {
    if (parser.getEventType() != XmlPullParser.START_DOCUMENT) {
      throw new IllegalArgumentException(
          "The start of document is expected, but actually not: " +
          parser.getPositionDescription());
    }
  }

  private static void assertEndDocument(XmlPullParser parser) throws XmlPullParserException {
    if (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
      throw new IllegalArgumentException(
          "The end of document is expected, but actually not: " + parser.getPositionDescription());
    }
  }

  private static void assertNotEndDocument(XmlPullParser parser) throws XmlPullParserException {
    if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
      throw new IllegalArgumentException(
          "Unexpected end of document is found: " + parser.getPositionDescription());
    }
  }

  private static void assertTagName(XmlPullParser parser, String expectedName) {
    String actualName = parser.getName();
    if (!actualName.equals(expectedName)) {
      throw new IllegalArgumentException(
          "Tag <" + expectedName + "> is expected, but found <" + actualName + ">: " +
          parser.getPositionDescription());
    }
  }

  private static void assertStartTag(XmlPullParser parser, String expectedName)
      throws XmlPullParserException {
    if (parser.getEventType() != XmlPullParser.START_TAG) {
      throw new IllegalArgumentException(
          "Start tag <" + expectedName + "> is expected: " + parser.getPositionDescription());
    }
    assertTagName(parser, expectedName);
  }

  private static void assertEndTag(XmlPullParser parser, String expectedName)
      throws XmlPullParserException {
    if (parser.getEventType() != XmlPullParser.END_TAG) {
      throw new IllegalArgumentException(
          "End tag </" + expectedName + "> is expected: " + parser.getPositionDescription());
    }
    assertTagName(parser, expectedName);
  }

  private final Resources resources;
  private final XmlResourceParser xmlResourceParser;
  private final Set<Integer> sourceIdSet = new HashSet<Integer>();
  private final int keyboardWidth;
  private final int keyboardHeight;

  public KeyboardParser(Resources resources, XmlResourceParser xmlResourceParser,
                        int keyboardWidth, int keyboardHeight) {
    if (resources == null) {
      throw new NullPointerException("resources shouldn't be null.");
    }
    if (xmlResourceParser == null) {
      throw new NullPointerException("xmlResourceParser shouldn't be null.");
    }

    this.resources = resources;
    this.xmlResourceParser = xmlResourceParser;
    this.keyboardWidth = keyboardWidth;
    this.keyboardHeight = keyboardHeight;
  }

  /**
   * Parses a XML resource and returns a Keyboard instance.
   */
  public Keyboard parseKeyboard() throws XmlPullParserException, IOException {
    // TODO(hidehiko): Refactor by spliting this method into two layers,
    //                 one is parse Keyboard element, and another is parsing a full xml file.
    XmlResourceParser parser = this.xmlResourceParser;

    // Initial two events should be START_DOCUMENT and then START_TAG.
    parser.next();
    assertStartDocument(parser);

    // The root element should be "Keyboard".
    parser.next();
    assertStartTag(parser, "Keyboard");

    // To clean the code, we probably should make a class which holds attributes of each
    // element in this method and following parseXxx methods, e.g.;
    //
    // private Attributes parseAttributes(int[] styles) {
    //   TypedArray attributes = ...
    //   try {
    //     Type1 var1 = ...;  // Read from attributes.
    //     Type2 var2 = ...;
    //     return new Attribute(var1, var2, ...);
    //   } finally {
    //     attributes.recycle();
    //   }
    // }
    //
    // However, it turned out that the code consumed the time a lot. So, considering the
    // situation, we'll use the following style in parseXxx methods in this class:
    //
    //    Type1 var1;
    //    Type2 var2;
    //    {
    //      TypedArray attributes = ...;
    //      try {
    //         // initialization of var1, var2, ...
    //      } finally {
    //        attributes.recycle();
    //      }
    //    }
    //    // Here, we can use var1 and var2 as these are initialized.
    //
    // By this code, the consumed time of parseKeyboard method is reduced by about 40%.
    // So, it should be beneficial enough.
    KeyAttributes keyAttributes;
    PopUpAttributes popUpAttributes;
    float flickThreshold;
    Optional<String> contentDescription = Optional.absent();
    {
      TypedArray attributes = resources.obtainAttributes(parser, R.styleable.Keyboard);
      try {
        DisplayMetrics metrics = resources.getDisplayMetrics();
        // The default keyWidth is 10% of the display for width, and 50px for height.
        keyAttributes = parseKeyAttributes(
            attributes,
            new KeyAttributes(keyboardWidth / 10, 50, 0, 0, null),
            metrics,
            this.keyboardWidth,
            this.keyboardHeight,
            R.styleable.Keyboard_keyWidth,
            R.styleable.Keyboard_keyHeight,
            R.styleable.Keyboard_horizontalGap,
            R.styleable.Keyboard_verticalGap,
            R.styleable.Keyboard_keyBackground);
        popUpAttributes = parsePopUpAttributes(
            attributes,
            metrics,
            this.keyboardWidth,
            R.styleable.Keyboard_popUpWidth,
            R.styleable.Keyboard_popUpHeight,
            R.styleable.Keyboard_popUpXOffset,
            R.styleable.Keyboard_popUpYOffset);
        flickThreshold = parseFlickThreshold(
            attributes, R.styleable.Keyboard_flickThreshold);
        contentDescription = Optional.fromNullable(
            attributes.getString(R.styleable.Keyboard_keyboardContentDescription));
      } finally {
        attributes.recycle();
      }
    }

    List<Row> rowList = new ArrayList<Row>();
    int y = 0;
    while (true) {
      parser.next();
      ignoreWhiteSpaceAndComment(parser);
      assertNotEndDocument(parser);
      if (parser.getEventType() == XmlResourceParser.END_TAG) {
        break;
      }
      Row row = parseRow(y, keyAttributes, popUpAttributes);
      rowList.add(row);
      y += row.getHeight() + row.getVerticalGap();
    }
    assertEndTag(parser, "Keyboard");

    // Meke sure the end of document.
    parser.next();
    ignoreWhiteSpaceAndComment(parser);
    assertEndDocument(parser);

    return buildKeyboard(contentDescription, rowList, flickThreshold);
  }

  /**
   * Parses a {@code Row} element, and returns a {@code Row} instance
   * containing a list of {@code Key}s.
   */
  private Row parseRow(
      int y, KeyAttributes defaultKeyAttributes, PopUpAttributes popUpAttributes)
      throws XmlPullParserException, IOException {
    XmlResourceParser parser = this.xmlResourceParser;
    assertStartTag(parser, "Row");

    int verticalGap;
    int rowHeight;
    int edgeFlags;
    {
      DisplayMetrics metrics = resources.getDisplayMetrics();
      TypedArray attributes = resources.obtainAttributes(parser, ROW_ATTRIBUTES);
      try {
        verticalGap = getDimensionOrFraction(
            attributes.peekValue(ROW_VERTICAL_GAP_INDEX),
            keyboardHeight, defaultKeyAttributes.verticalGap, metrics);
        rowHeight = getDimensionOrFraction(
            attributes.peekValue(ROW_KEY_HEIGHT_INDEX), keyboardHeight,
            defaultKeyAttributes.height, metrics);
        edgeFlags = attributes.getInt(ROW_ROW_EDGE_FLAGS_INDEX, 0);
      } finally {
        attributes.recycle();
      }
    }

    List<Key> keyList = new ArrayList<Key>();
    int x = 0;
    while (true) {
      parser.next();
      ignoreWhiteSpaceAndComment(parser);
      assertNotEndDocument(parser);
      if (parser.getEventType() == XmlResourceParser.END_TAG) {
        break;
      }
      if ("Key".equals(parser.getName())) {
        Key key = parseKey(x, y, edgeFlags, defaultKeyAttributes, popUpAttributes);
        keyList.add(key);
        x += key.getWidth();
      } else if ("Spacer".equals(parser.getName())) {
        Key key = parseSpacer(x, y, edgeFlags, defaultKeyAttributes);
        keyList.add(key);
        x += key.getWidth();
      }
    }

    assertEndTag(parser, "Row");
    return buildRow(keyList, rowHeight, verticalGap);
  }

  /**
   * Parses a {@code Key} element, and returns an instance.
   */
  private Key parseKey(int x, int y, int edgeFlags,
                       KeyAttributes defaultKeyAttributes, PopUpAttributes popUpAttributes)
      throws XmlPullParserException, IOException {
    XmlResourceParser parser = this.xmlResourceParser;
    assertStartTag(parser, "Key");

    KeyAttributes keyAttributes;
    boolean isRepeatable;
    boolean isModifier;
    boolean isSticky;
    {
      TypedArray attributes = resources.obtainAttributes(parser, KEY_ATTRIBUTES);
      try {
        DisplayMetrics metrics = resources.getDisplayMetrics();
        keyAttributes = parseKeyAttributes(
            attributes, defaultKeyAttributes, metrics, keyboardWidth, keyboardHeight,
            KEY_KEY_WIDTH_INDEX, KEY_KEY_HEIGHT_INDEX, KEY_HORIZONTAL_GAP_INDEX, -1,
            KEY_KEY_BACKGROUND_INDEX);
        edgeFlags |= attributes.getInt(KEY_KEY_EDGE_FLAGS_INDEX, 0);
        isRepeatable = attributes.getBoolean(KEY_IS_REPEATABLE_INDEX, false);
        isModifier = attributes.getBoolean(KEY_IS_MODIFIER_INDEX, false);
        isSticky = attributes.getBoolean(KEY_IS_STICKY_INDEX, false);
      } finally {
        attributes.recycle();
      }
    }

    List<KeyState> keyStateList = new ArrayList<KeyState>();
    while (true) {
      parser.next();
      ignoreWhiteSpaceAndComment(parser);
      assertNotEndDocument(parser);
      if (parser.getEventType() == XmlResourceParser.END_TAG) {
        break;
      }

      keyStateList.add(
          parseKeyState(keyAttributes.keyBackgroundDrawableType, popUpAttributes));
    }

    // At the moment, we just accept keys which has default state.
    boolean hasDefault = false;
    boolean hasLongPressKeyCode = false;
    for (KeyState keyState : keyStateList) {
      if (keyState.getMetaStateSet().isEmpty()) {
        hasDefault = true;
        if (keyState.getFlick(Flick.Direction.CENTER).getKeyEntity().getLongPressKeyCode() !=
            KeyEntity.INVALID_KEY_CODE) {
          hasLongPressKeyCode = true;
        }
        break;
      }
    }
    if (!hasDefault) {
      throw new IllegalArgumentException(
          "No default KeyState element is found: " + parser.getPositionDescription());
    }

    if (isRepeatable && hasLongPressKeyCode) {
      throw new IllegalArgumentException(
          "The key has both isRepeatable attribute and longPressKeyCode: " +
          parser.getPositionDescription());
    }

    assertEndTag(parser, "Key");
    return new Key(
        x, y, keyAttributes.width, keyAttributes.height, keyAttributes.horizontalGap,
        edgeFlags, isRepeatable, isModifier, isSticky, Stick.EVEN, keyStateList);
  }

  /**
   * Parses a {@code Spacer} element, and returns an instance.
   */
  private Key parseSpacer(int x, int y, int edgeFlags, KeyAttributes defaultKeyAttributes)
      throws XmlPullParserException, IOException {
    XmlResourceParser parser = this.xmlResourceParser;
    DisplayMetrics metrics = resources.getDisplayMetrics();
    assertStartTag(parser, "Spacer");

    KeyAttributes keyAttributes;
    Stick stick;
    {
      TypedArray attributes = resources.obtainAttributes(parser, SPACER_ATTRIBUTES);
      try {
        keyAttributes = parseKeyAttributes(
            attributes, defaultKeyAttributes, metrics, keyboardWidth, keyboardHeight,
            -1, SPACER_KEY_HEIGHT_INDEX, SPACER_HORIZONTAL_GAP_INDEX, -1, -1);
        edgeFlags |= attributes.getInt(SPACER_KEY_EDGE_FLAGS_INDEX, 0);
        stick = Stick.values()[attributes.getInt(SPACER_STICK_INDEX, 0)];
      } finally {
        attributes.recycle();
      }
    }

    parser.next();
    assertEndTag(parser, "Spacer");

    // Returns a dummy key object.
    return new Key(
        x, y, keyAttributes.horizontalGap, keyAttributes.height,
        0, edgeFlags, false, false, false, stick, Collections.<KeyState>emptyList());
  }

  private KeyState parseKeyState(DrawableType defaultBackgroundDrawableType,
                                 PopUpAttributes popUpAttributes)
      throws XmlPullParserException, IOException {
    XmlResourceParser parser = this.xmlResourceParser;
    assertStartTag(parser, "KeyState");

    String contentDescription;
    DrawableType backgroundDrawableType;
    Set<KeyState.MetaState> metaStateSet;
    Set<KeyState.MetaState> nextAddMetaState;
    Set<KeyState.MetaState> nextRemoveMetaState;
    {
      TypedArray attributes = resources.obtainAttributes(parser, KEY_STATE_ATTRIBUTES);
      try {
        contentDescription = Objects.firstNonNull(
            attributes.getText(KEY_STATE_CONTENT_DESCRIPTION_INDEX), "").toString();
        backgroundDrawableType = parseKeyBackgroundDrawableType(
            attributes, KEY_STATE_KEY_BACKGROUND_INDEX, defaultBackgroundDrawableType);
        metaStateSet = parseMetaState(attributes, KEY_STATE_META_STATE_INDEX);
        nextAddMetaState = parseMetaState(attributes, KEY_STATE_NEXT_META_STATE_INDEX);
        nextRemoveMetaState = parseMetaState(attributes, KEY_STATE_NEXT_REMOVED_META_STATES_INDEX);
      } finally {
        attributes.recycle();
      }
    }

    List<Flick> flickList = new ArrayList<Flick>();
    while (true) {
      parser.next();
      ignoreWhiteSpaceAndComment(parser);
      assertNotEndDocument(parser);
      if (parser.getEventType() == XmlResourceParser.END_TAG) {
        break;
      }
      flickList.add(parseFlick(backgroundDrawableType, popUpAttributes));
    }

    // At the moment, we support only keys which has flick data to the CENTER direction.
    boolean isCenterFound = false;
    for (Flick flick : flickList) {
      if (flick.getDirection() == Flick.Direction.CENTER) {
        isCenterFound = true;
        break;
      }
    }
    if (!isCenterFound) {
      throw new IllegalArgumentException(
          "No CENTER flick element is found: " + parser.getPositionDescription());
    }

    assertEndTag(parser, "KeyState");
    return new KeyState(contentDescription, metaStateSet, nextAddMetaState, nextRemoveMetaState,
                        flickList);
  }

  private Flick parseFlick(DrawableType backgroundDrawableType,
                           PopUpAttributes popUpAttributes)
      throws XmlPullParserException, IOException {
    XmlResourceParser parser = this.xmlResourceParser;
    assertStartTag(parser, "Flick");

    Flick.Direction direction;
    {
      TypedArray attributes = resources.obtainAttributes(parser, R.styleable.Flick);
      try {
        direction = parseFlickDirection(attributes, R.styleable.Flick_direction);
      } finally {
        attributes.recycle();
      }
    }

    parser.next();
    KeyEntity entity = parseKeyEntity(backgroundDrawableType, popUpAttributes);

    if (entity.getLongPressKeyCode() != KeyEntity.INVALID_KEY_CODE &&
        direction != Flick.Direction.CENTER) {
      throw new IllegalArgumentException(
          "longPressKeyCode can be set to only a KenEntity for CENTER direction: " +
          parser.getPositionDescription());
    }

    parser.next();
    assertEndTag(parser, "Flick");

    return new Flick(direction, entity);
  }

  private KeyEntity parseKeyEntity(
      DrawableType backgroundDrawableType, PopUpAttributes popUpAttributes)
      throws XmlPullParserException, IOException {
    XmlResourceParser parser = this.xmlResourceParser;
    assertStartTag(parser, "KeyEntity");

    int sourceId;
    int keyCode;
    int longPressKeyCode;
    int keyIconResourceId;
    String keyCharacter;
    @SuppressWarnings("unused")
    DrawableType keyBackgroundDrawableType;
    boolean flickHighlight;
    {
      TypedArray attributes = resources.obtainAttributes(parser, KEY_ENTITY_ATTRIBUTES);
      try {
        sourceId = getSourceId(attributes.peekValue(KEY_ENTITY_SOURCE_ID_INDEX), 0);
        if (!sourceIdSet.add(sourceId)) {
          //  Same sourceId is found.
          throw new IllegalArgumentException(
              "Duplicataed sourceId is found: " + xmlResourceParser.getPositionDescription());
        }
        keyCode = getCode(
            attributes.peekValue(KEY_ENTITY_KEY_CODE_INDEX), KeyEntity.INVALID_KEY_CODE);
        longPressKeyCode = getCode(attributes.peekValue(KEY_ENTITY_LONG_PRESS_KEY_CODE_INDEX),
                                   KeyEntity.INVALID_KEY_CODE);
        keyIconResourceId = attributes.getResourceId(KEY_ENTITY_KEY_ICON_INDEX, 0);
        keyCharacter = attributes.getString(KEY_ENTITY_KEY_CHAR_INDEX);
        flickHighlight = attributes.getBoolean(KEY_ENTITY_FLICK_HIGHLIGHT_INDEX, false);
      } finally {
        attributes.recycle();
      }
    }

    parser.next();
    ignoreWhiteSpaceAndComment(parser);

    PopUp popUp = null;
    if (parser.getEventType() == XmlResourceParser.START_TAG) {
      popUp = parsePopUp(popUpAttributes);
      parser.next();
      ignoreWhiteSpaceAndComment(parser);
    }

    assertEndTag(parser, "KeyEntity");

    return new KeyEntity(sourceId, keyCode, longPressKeyCode, keyIconResourceId, keyCharacter,
                         backgroundDrawableType, flickHighlight, popUp);
  }

  private PopUp parsePopUp(PopUpAttributes popUpAttributes)
      throws XmlPullParserException, IOException {
    XmlResourceParser parser = this.xmlResourceParser;
    assertStartTag(parser, "PopUp");

    int popUpIconResourceId;
    {
      TypedArray attributes = resources.obtainAttributes(parser, R.styleable.PopUp);
      try {
        popUpIconResourceId = attributes.getResourceId(R.styleable.PopUp_popUpIcon, 0);
      } finally {
        attributes.recycle();
      }
    }
    parser.next();
    assertEndTag(parser, "PopUp");

    return new PopUp(popUpIconResourceId,
                     popUpAttributes.popUpWidth,
                     popUpAttributes.popUpHeight,
                     popUpAttributes.popUpXOffset,
                     popUpAttributes.popUpYOffset);
  }

  private float parseFlickThreshold(TypedArray attributes, int index) {
    float flickThreshold = attributes.getDimension(
        index, resources.getDimension(R.dimen.default_flick_threshold));
    if (flickThreshold <= 0) {
      throw new IllegalArgumentException(
          "flickThreshold must be greater than 0.  value = " + flickThreshold);
    }
    return flickThreshold;
  }

  private static KeyAttributes parseKeyAttributes(
      TypedArray attributes, KeyAttributes defaultValue, DisplayMetrics metrics,
      int keyboardWidth, int keyboardHeight,
      int keyWidthIndex, int keyHeightIndex, int horizontalGapIndex, int verticalGapIndex,
      int keyBackgroundIndex) {
    int keyWidth = (keyWidthIndex >= 0)
        ? getDimensionOrFraction(
              attributes.peekValue(keyWidthIndex), keyboardWidth,
              defaultValue.width, metrics)
        : defaultValue.width;
    int keyHeight = (keyHeightIndex >= 0)
        ? getDimensionOrFraction(
              attributes.peekValue(keyHeightIndex), keyboardHeight,
              defaultValue.height, metrics)
        : defaultValue.height;

    int horizontalGap = (horizontalGapIndex >= 0)
        ? getDimensionOrFraction(
              attributes.peekValue(horizontalGapIndex),
              keyboardWidth, defaultValue.horizontalGap, metrics)
        : defaultValue.horizontalGap;
    int verticalGap = (verticalGapIndex >= 0)
        ? getDimensionOrFraction(
              attributes.peekValue(verticalGapIndex),
              keyboardHeight, defaultValue.verticalGap, metrics)
        : defaultValue.verticalGap;

    DrawableType keyBackgroundDrawableType = parseKeyBackgroundDrawableType(
        attributes, keyBackgroundIndex, defaultValue.keyBackgroundDrawableType);
    return new KeyAttributes(
        keyWidth, keyHeight, horizontalGap, verticalGap, keyBackgroundDrawableType);
  }

  private static DrawableType parseKeyBackgroundDrawableType(
      TypedArray attributes, int index, DrawableType defaultValue) {
    if (index < 0) {
      return defaultValue;
    }
    int value = attributes.getInt(index, -1);
    return (value < 0) ? defaultValue : KEY_BACKGROUND_DRAWABLE_TYPE_MAP[value];
  }

  private static PopUpAttributes parsePopUpAttributes(
      TypedArray attributes, DisplayMetrics metrics, int keyboardWidth,
      int popUpWidthIndex, int popUpHeightIndex, int popUpXOffsetIndex, int popUpYOffsetIndex) {
    int popUpWidth = getDimensionOrFraction(
        attributes.peekValue(popUpWidthIndex), keyboardWidth, 0, metrics);
    int popUpHeight = getDimensionOrFraction(
        attributes.peekValue(popUpHeightIndex), keyboardWidth, 0, metrics);
    int popUpXOffset = getDimensionOrFraction(
        attributes.peekValue(popUpXOffsetIndex), keyboardWidth, 0, metrics);
    int popUpYOffset = getDimensionOrFraction(
        attributes.peekValue(popUpYOffsetIndex), keyboardWidth, 0, metrics);
    return new PopUpAttributes(popUpWidth, popUpHeight, popUpXOffset, popUpYOffset);
  }

  /**
   * Returns set of MetaState.
   *
   * <p>Empty set is returned if corresponding attribute is not found.
   * This is used for default KeyState.
   */
  private Set<KeyState.MetaState> parseMetaState(TypedArray attributes, int index) {
    int metaStateFlags = attributes.getInt(index, 0);
    if (metaStateFlags == 0) {
      return Collections.emptySet();
    }

    Set<KeyState.MetaState> result = EnumSet.noneOf(KeyState.MetaState.class);
    for (int i = 0; i < Integer.SIZE; ++i) {
      int flag = metaStateFlags & (1 << i);
      if (flag != 0) {
        result.add(KeyState.MetaState.valueOf(flag));
      }
    }
    return result;
  }

  private Flick.Direction parseFlickDirection(TypedArray attributes, int index) {
    return Flick.Direction.valueOf(attributes.getInt(index, Flick.Direction.CENTER.index));
  }

  protected Keyboard buildKeyboard(
      Optional<String> contentDescription, List<Row> rowList, float flickThreshold) {
    return new Keyboard(Preconditions.checkNotNull(contentDescription),
                        Preconditions.checkNotNull(rowList), flickThreshold);
  }

  protected Row buildRow(List<Key> keyList, int height, int verticalGap) {
    return new Row(keyList, height, verticalGap);
  }
}
