<!--
  -- Copyright 2013 The Chromium Authors. All rights reserved.
  -- Use of this source code is governed by a BSD-style license that can be
  -- found in the LICENSE file.
  -->

<polymer-element name="kb-shift-key"
    attributes="lowerCaseKeysetId upperCaseKeysetId"
    class="shift dark" char="Shift" on-pointerout="out" extends="kb-key">
  <script>
    (function () {

      /**
       * The possible states of the shift key.
       * Unlocked is the default state. Locked for capslocked, pressed is a
       * key-down and tapped for a key-down followed by an immediate key-up.
       * @const
       * @type {Enum}
       */
      var KEY_STATES = {
        PRESSED: "pressed", // Key-down on shift key.
        LOCKED: "locked", // Key is capslocked.
        UNLOCKED: "unlocked", // Default state.
        TAPPED: "tapped", // Key-down followed by key-up.
        CHORDING: "chording" // Key-down followed by other keys.
      };

      /**
       * The pointerdown event on shiftkey that may eventually trigger chording
       * state. pointerId and eventTarget are the two fields that is used now.
       * @type {PointerEvent}
       */
      var enterChordingEvent = undefined;

      /**
       * Uses a closure to define one long press timer among all shift keys
       * regardless of the layout they are in.
       * @type {function}
       */
      var shiftLongPressTimer = undefined;

      /**
       * The current state of the shift key.
       * @type {Enum}
       */
      var state = KEY_STATES.UNLOCKED;

      Polymer('kb-shift-key', {
        /**
         * Defines how capslock effects keyset transition. We always transition
         * from the lowerCaseKeysetId to the upperCaseKeysetId if capslock is
         * on.
         * @type {string}
         */
        lowerCaseKeysetId: 'lower',
        upperCaseKeysetId: 'upper',

        up: function(event) {
          if (state == KEY_STATES.CHORDING &&
              event.pointerId != enterChordingEvent.pointerId) {
            // Disables all other pointer events on shift keys when chording.
            return;
          }
          switch (state) {
            case KEY_STATES.PRESSED:
              state = KEY_STATES.TAPPED;
              break;
            case KEY_STATES.CHORDING:
              // Leaves chording only if the pointer that triggered it is
              // released.
              state = KEY_STATES.UNLOCKED;
              break;
            default:
              break;
          }
          // When releasing the shift key, it is not the same shift key that was
          // pressed. Updates the pointerId of the releasing shift key to make
          // sure key-up event fires correctly in kb-key-base.
          this.pointerId = enterChordingEvent.pointerId;
          this.super([event]);
        },

        out: function(event) {
          // Sliding off the shift key while chording is treated as a key-up.
          // Note that we switch to a new keyset on shift keydown, and a finger
          // movement on the new shift key will trigger this function being
          // called on the old shift key. We should not end chording in that
          // case.
          if (state == KEY_STATES.CHORDING &&
              event.pointerId == enterChordingEvent.pointerId &&
              event.target != enterChordingEvent.target) {
            state = KEY_STATES.UNLOCKED;
            var detail = this.populateDetails('out');
            this.fire("key-out", detail);
          }
        },

        down: function(event) {
          // First transition state so that populateDetails generates
          // correct data.
          switch (state) {
            case KEY_STATES.UNLOCKED:
              state = KEY_STATES.PRESSED;
              break;
            case KEY_STATES.TAPPED:
            case KEY_STATES.LOCKED:
              state = KEY_STATES.UNLOCKED;
              break;
            case KEY_STATES.PRESSED:
            case KEY_STATES.CHORDING:
              // We pressed another shift key at the same time,
              // so ignore second press.
              return;
            default:
              console.error("Undefined shift key state: " + state);
              break;
          }
          enterChordingEvent = event;
          // Trigger parent behaviour.
          this.super([event]);
          this.fire('enable-sel');
          // Populate double click transition details.
          var detail = {};
          detail.char = this.char || this.textContent;
          detail.toKeyset = this.upperCaseKeysetId;
          detail.nextKeyset = undefined;
          detail.callback = this.onDoubleClick;
          this.fire('enable-dbl', detail);
        },

        generateLongPressTimer: function() {
          return this.asyncMethod(function() {
            var detail = this.populateDetails();
            if (state == KEY_STATES.LOCKED) {
              // We don't care about the longpress if we are already
              // capitalized.
              return;
            } else {
              state = KEY_STATES.LOCKED;
              detail.toKeyset = this.upperCaseKeysetId;
              detail.nextKeyset = undefined;
            }
            this.fire('key-longpress', detail);
          }, null, LONGPRESS_DELAY_MSEC);
        },

        /**
         * Callback function for when a double click is triggered.
         */
        onDoubleClick: function() {
          state = KEY_STATES.LOCKED;
        },

        /**
         * Notifies shift key that a non-control key was pressed down.
         * A control key is defined as one of shift, control or alt.
         */
        onNonControlKeyDown: function() {
           switch (state) {
             case (KEY_STATES.TAPPED):
               state = KEY_STATES.UNLOCKED;
               break;
             case (KEY_STATES.PRESSED):
               state = KEY_STATES.CHORDING;
               // Disable longpress timer.
               clearTimeout(shiftLongPressTimer);
               break;
             default:
               break;
           }
         },

        /**
         * Callback function for when a space is pressed after punctuation.
         * @return {Object} The keyset transitions the keyboard should make.
         */
        onSpaceAfterPunctuation: function() {
           var detail = {};
           detail.toKeyset = this.upperCaseKeysetId;
           detail.nextKeyset = this.lowerCaseKeysetId;
           state = KEY_STATES.TAPPED;
           return detail;
        },

        populateDetails: function(caller) {
          var detail = this.super([caller]);
          switch(state) {
            case(KEY_STATES.LOCKED):
              detail.toKeyset = this.upperCaseKeysetId;
              break;
            case(KEY_STATES.UNLOCKED):
              detail.toKeyset = this.lowerCaseKeysetId;
              break;
            case(KEY_STATES.PRESSED):
              detail.toKeyset = this.upperCaseKeysetId;
              break;
            case(KEY_STATES.TAPPED):
              detail.toKeyset = this.upperCaseKeysetId;
              detail.nextKeyset = this.lowerCaseKeysetId;
              break;
            case(KEY_STATES.CHORDING):
              detail.toKeyset = this.lowerCaseKeysetId;
              break;
            default:
              break;
          }
          return detail;
        },

        /**
         *  Resets the shift key state.
         */
        reset: function() {
          state = KEY_STATES.UNLOCKED;
        },

        /**
         * Overrides longPressTimer for the shift key.
         */
        get longPressTimer() {
          return shiftLongPressTimer;
        },

        set longPressTimer(timer) {
          shiftLongPressTimer = timer;
        },

        get state() {
          return state;
        },

        get textKeyset() {
          switch (state) {
            case KEY_STATES.UNLOCKED:
              return this.lowerCaseKeysetId;
            default:
              return this.upperCaseKeysetId;
          }
        },
      });
    })();
  </script>
</polymer-element>
