/**
 * @license
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

CLASS({
  name:  'Halo',
  package: 'foam.ui.md',

  extendsModel: 'foam.graphics.Circle',

  constant: {
    RING_INNER_COLOR: 'rgba(0, 0, 0, 0)'
  },

  properties: [
    {
      name: 'style',
      documentation: 'solid|ring',
      defaultValue: 'solid',
      postSet: function(_, style) {
        if ( style !== this.RING_INNER_COLOR ) this.setColorAndBorder();
      }
    },
    {
      name: 'state_',
      defaultValue: 'default' // pressed, released
    },
    {
      name: 'easeInTime',
      defaultValue: 200
    },
    {
      name: 'easeOutTime',
      defaultValue: 150
    },
    {
      name: 'startAlpha',
      defaultValue: 0.8
    },
    {
      name: 'pressedAlpha',
      defaultValue: 0.4
    },
    {
      name: 'finishAlpha',
      defaultValue: 0
    }
  ],

  methods: [
    {
      name: 'setColorAndBorder',
      code: function() {
        if ( this.style === 'ring' ) {
          var color = this.color;
          this.border = color;
          this.borderWidth = 12;
          this.color = this.RING_INNER_COLOR;
        }
      }
    },
    {
      name: 'initCView',
      code: function() {
        this.$.addEventListener('mousedown',   this.onMouseDown);
        this.$.addEventListener('mouseup',     this.onMouseUp);
        this.$.addEventListener('mouseleave',  this.onMouseUp);
        this.$.addEventListener('touchstart',  this.onMouseDown);
        this.$.addEventListener('touchend',    this.onMouseUp);
        this.$.addEventListener('touchleave',  this.onMouseUp);
        this.$.addEventListener('touchcancel', this.onMouseUp);
      }
    }
  ],

  listeners: [
    {
      name: 'onMouseDown',
      code: function(evt) {
        if ( this.state_ !== 'default' ) return;

        this.state_ = 'pressing';

        if ( evt.type === 'touchstart' ) {
          var rect = this.$.getBoundingClientRect();
          var t = evt.touches[0];
          this.x = t.pageX - rect.left;
          this.y = t.pageY - rect.top;
        } else {
          this.x = evt.offsetX;
          this.y = evt.offsetY;
        }
        this.r = 2;
        this.alpha = this.startAlpha;
        this.X.animate(this.easeInTime, function() {
          this.x = this.parent.width/2;
          this.y = this.parent.height/2;
          this.r = Math.min(28, Math.min(this.$.width, this.parent.height)/2);
          this.alpha = this.pressedAlpha;
        }.bind(this), undefined, function() {
          if ( this.state_ === 'cancelled' ) {
            this.state_ = 'pressed';
            this.onMouseUp();
          } else {
            this.state_ = 'pressed';
          }
        }.bind(this))();
      }
    },
    {
      name: 'onMouseUp',
      code: function(evt) {
        // This line shouldn't be necessary but we're getting stray
        // onMouseUp events when the cursor moves over the button.
        if ( this.state_ === 'default' ) return;

        if ( this.state_ === 'pressing' ) { this.state_ = 'cancelled'; return; }
        if ( this.state_ === 'cancelled' ) return;
        this.state_ = 'released';

        this.X.animate(
          this.easeOutTime,
          function() { this.alpha = this.finishAlpha; }.bind(this),
          Movement.easeIn(.5),
          function() { if ( this.state_ === 'released' ) this.state_ = 'default'; }.bind(this))();
      }
    }
  ]
});

@@ -2216,22 +2216,227 @@
       %7D%0A
+    %7D,%0A    %7B%0A      name: 'isTouchInRect',%0A      code: function(t, rect) %7B%0A        return t.pageX %3E= rect.left && t.pageX %3C= rect.right &&%0A            t.pageY %3E= rect.top && t.pageY %3C= rect.bottom;%0A      %7D%0A
     %7D%0A
-
   %5D,%0A%0A  
@@ -2692,23 +2692,103 @@
 ct()
-;%0A          var
+, touchFound = false, t;%0A          for ( var i = 0; i %3C evt.touches.length; ++i ) %7B%0A           
  t =
@@ -2804,12 +2804,133 @@
 hes%5B
-0
+i
 %5D;%0A
+            if ( this.isTouchInRect(t, rect) ) %7B touchFound = true; break; %7D%0A          %7D%0A          if ( touchFound ) %7B%0A  
     
@@ -2967,32 +2967,34 @@
 left;%0A          
+ 
+ 
 this.y = t.pageY
@@ -3006,16 +3006,245 @@
 ct.top;%0A
+          %7D else %7B%0A            // Default to center of element.%0A            console.warn('No touches', evt.touches, 'in element rect', rect);%0A            this.x = rect.width / 2;%0A            this.y = rect.height / 2;%0A          %7D%0A
         

Fix halo touch events: locate correct event in TouchList for positioning halo