// --------------------------------------------------------------------
// wm3d - A Flash Molecular Viewer
//
// Copyright (c) 2011-2013, tamanegi (tamanegi@users.sourceforge.jp)
// All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// --------------------------------------------------------------------

import flash.display.Sprite;
import flash.display.Stage;

import flash.geom.Vector3D;

import flash.Vector;

import flash.events.Event;
import flash.events.MouseEvent;

/**
  Controller or Player

  Container of play/stop, enlarge/shrink buttons shown in the bottom of the
  window.
**/

class WMController extends Sprite {
  private var wm:Watermelon;

  /**
    background color
  **/
  @:isVar public var bgColor( get, set ):Int;
    /**
      getter of `bgColor`
    **/
    public function get_bgColor():Int { return( bgColor ); }
    /**
      setter of `bgColor`
    **/
    public function set_bgColor( c:Int ):Int {
      bgColor = c;
      return( bgColor );
    }

  /**
    background alpha
  **/
  @:isVar public var bgAlpha( get, set ):Float;
    /**
      getter of `bgAlpha`
    **/
    public function get_bgAlpha():Float { return( bgAlpha ); }
    /**
      setter of `bgAlpha`
    **/
    public function set_bgAlpha( a:Float ):Float {
      bgAlpha = a;
      return( bgAlpha );
    }

  /**
    button color; this value is used for all the buttons
  **/
  @:isVar public var buttonColor( get, set ):Int;
    /**
      getter of `buttonColor`
    **/
    public function get_buttonColor():Int { return( buttonColor ); }
    /**
      setter of `buttonColor`
    **/
    public function set_buttonColor( c:Int ):Int {
      buttonColor = c;
      return( buttonColor );
    }

  /**
    button alpha; common for all buttons
  **/
  @:isVar public var buttonAlpha( get, set ):Float;
    /**
      getter of `buttonAlpha`
    **/
    public function get_buttonAlpha():Float { return( buttonAlpha ); }
    /**
      setter of `buttonAlpha`
    **/
    public function set_buttonAlpha( a:Float ):Float {
      buttonAlpha = a;
      return( buttonAlpha );
    }

  /**
    line width
  **/
  @:isVar public var lineWidth( get, set ):Float;
    /**
      getter of `lineWidth`
    **/
    public function get_lineWidth():Float { return( lineWidth ); }
    /**
      setter of `lineWidth`
    **/
    public function set_lineWidth( w:Float ):Float {
      lineWidth = w;
      return( lineWidth );
    }

  /**
    button width
  **/
  @:isVar public var buttonWidth( get, set ):Int;
    /**
      getter of `buttonWidth`
    **/
    public function get_buttonWidth():Int { return( buttonWidth ); }
    /**
      setter of `buttonWidth`
    **/
    public function set_buttonWidth( w:Int ):Int {
      buttonWidth = w;
      return( buttonWidth );
    }

  /**
    height of buttons
  **/
  @:isVar public var buttonHeight( get, set ):Int;
    /**
      getter for `buttonHeight`
    **/
    public function get_buttonHeight():Int { return( buttonHeight ); }
    /**
      setter for `buttonHeight`
    **/
    public function set_buttonHeight( h:Int ):Int {
      buttonHeight = h;
      return( buttonHeight );
    }

  /**
    button margin
  **/
  @:isVar public var margin( get, set ):Int;
    /**
      getter of `margin`
    **/
    public function get_margin():Int { return( margin ); }
    /**
      setter of `margin`
    **/
    public function set_margin( m:Int ):Int {
      margin = m;
      return( margin );
    }

  // ######################################################################

  /**
    Constructor; the parent manager class `w` msut be given
    Default value of variables are assigned here.

    - bgColor: 0xFFFFFF (white)
    - bgAlpha: 0.0 (transparent)
    - buttonColor: 0x888888 (gray)
    - buttonAlpha: 1.0 (opaque)
    - buttonWidth: 20 (in pixel)
    - buttonHeight: 20 (in pixel)
    - margin: 2 (in pixel)
    - linewidth: 3 (in pixel)
  **/
  public function new( w:Watermelon ) {
    super();
    wm = w;

    // default values
    bgColor = 0xFFFFFF;
    bgAlpha = 0.0;
    buttonColor = 0x888888;
    buttonAlpha = 1.0;
    buttonWidth = 20;
    buttonHeight = 20;
    margin = 2;
    lineWidth = 3;
  }

  // misc funcs
  /**
    check whether the controller is created
  **/
  public function enabled():Bool {
    return( this.numChildren > 0 );
  }

  /**
    draw buttons
  **/
  public function draw() {
    this.graphics.clear();
    this.removeChildren();

    fillBackground();
    createForwardButton();
    createGoToLastButton();
    createBackButton();
    createGoToInitButton();

    createPlayer();
    createScaler();

    // controller position
    this.y = wm.stage.stageHeight - buttonHeight;

    // controller event listener
    var ref = this;
    this.addEventListener( MouseEvent.ROLL_OVER,
                           function( e:Event ) {
                             ref.alpha = 1.0;
                           } );
    this.addEventListener( MouseEvent.ROLL_OUT,
                           function( e:Event ) {
                             ref.alpha = 0.0;
                           } );

    return( this );
  }

  private function createScaler():Void {
    var scaler = new Sprite();
    scaler.graphics.beginFill( bgColor, bgAlpha );
    scaler.graphics.drawRect( 0, 0, 3 * buttonWidth + margin, buttonHeight );
    scaler.graphics.endFill();

    // initializer
    var initializer = new Sprite();
    initializer.graphics.beginFill( bgColor, bgAlpha );
    initializer.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    initializer.graphics.endFill();
    initializer.graphics.lineStyle( lineWidth, buttonColor, buttonAlpha );
    var rad:Float = 0.35 * Math.min( buttonWidth, buttonHeight );
    initializer.graphics.drawCircle( 0.65 * buttonWidth, 0.35 * buttonHeight, rad );
    var vec:Float = 1.0 / Math.sqrt( 2 );
    var vm:Float = 0.65 * Math.min( buttonWidth, buttonHeight );
    initializer.graphics.moveTo( 0.65 * buttonWidth - rad * vec,
                                 0.35 * buttonHeight + rad * vec );
    initializer.graphics.lineTo( 0.65 * buttonWidth - vm,
                                 0.35 * buttonHeight + vm );
    scaler.addChild( initializer );
    initializer.x = buttonWidth;
    var ref = wm;
    initializer.addEventListener( MouseEvent.CLICK,
                                  function( e:MouseEvent ) {
                                    var v3:Vector<Vector3D> = new Vector<Vector3D>(3);
                                    v3 = ref.states.mpos.decompose();
                                    v3[2].setTo( 1.0, 1.0, 1.0 );
                                    ref.states.mpos.recompose( v3 );
                                    ref.states.updateMPos = true;
                                  } );

    // enlarger
    var enlarger:Sprite = new Sprite();
    enlarger.graphics.beginFill( bgColor, bgAlpha );
    enlarger.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    enlarger.graphics.endFill();
    enlarger.graphics.lineStyle( lineWidth, buttonColor, buttonAlpha );
    enlarger.graphics.moveTo( margin, buttonHeight / 2 );
    enlarger.graphics.lineTo( buttonWidth - margin, buttonHeight / 2 );
    enlarger.graphics.moveTo( buttonWidth / 2, margin );
    enlarger.graphics.lineTo( buttonWidth / 2, buttonHeight - 2 );
    scaler.addChild( enlarger );
    enlarger.x = scaler.width - buttonWidth;
    enlarger.addEventListener( MouseEvent.CLICK,
                               function( e:MouseEvent ) {
                                 ref.states.changeScale( 5 );
                               } );

    // shrinker
    var shrinker:Sprite = new Sprite();
    shrinker.graphics.beginFill( bgColor, bgAlpha );
    shrinker.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    shrinker.graphics.endFill();
    shrinker.graphics.lineStyle( lineWidth, buttonColor, buttonAlpha );
    shrinker.graphics.moveTo( margin, buttonHeight / 2 );
    shrinker.graphics.lineTo( buttonWidth - margin, buttonHeight / 2 );
    scaler.addChild( shrinker );
    shrinker.x = 0;
    shrinker.addEventListener( MouseEvent.CLICK,
                               function( e:MouseEvent ) {
                                 ref.states.changeScale( -5 );
                               } );

    this.addChild( scaler );
    scaler.x = wm.stage.stageWidth / 2 + buttonWidth;
  }

  private function createPlayer():Void {
    var player:Sprite = new Sprite();
    player.graphics.beginFill( bgColor, bgAlpha );
    player.graphics.drawRect( 0, 0, 3 * buttonWidth, buttonHeight );
    player.graphics.endFill();
    player.x = wm.stage.stageWidth / 2 - player.width - buttonWidth;

    // stop buttton
    var stopbutton:Sprite = new Sprite();
    stopbutton.graphics.beginFill( bgColor, bgAlpha );
    stopbutton.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    stopbutton.graphics.endFill();
    stopbutton.graphics.beginFill( buttonColor, buttonAlpha );
    stopbutton.graphics.drawRect( margin, margin, buttonWidth - 2 * margin, buttonHeight - 2 * margin);
    stopbutton.graphics.endFill();
    stopbutton.x = buttonWidth;
    player.addChild( stopbutton );
    stopbutton.addEventListener( MouseEvent.CLICK, wm.states.pausePlay );

    // play forward
    var playforward:Sprite = new Sprite();
    playforward.graphics.beginFill( bgColor, bgAlpha );
    playforward.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    playforward.graphics.endFill();
    playforward.graphics.lineStyle( lineWidth, buttonColor, buttonAlpha );
    playforward.graphics.moveTo( margin, buttonHeight / 2 );
    playforward.graphics.lineTo( buttonWidth - margin, buttonHeight / 2 );
    playforward.graphics.lineTo( buttonWidth / 2, margin );
    playforward.graphics.moveTo( buttonWidth - margin, buttonHeight / 2 );
    playforward.graphics.lineTo( buttonWidth / 2, buttonHeight - margin );
    playforward.x = player.width - buttonWidth;
    player.addChild( playforward );
    playforward.addEventListener( MouseEvent.CLICK, wm.states.playForward );

    // play backward
    var playbackward:Sprite = new Sprite();
    playbackward.graphics.beginFill( bgColor, bgAlpha );
    playbackward.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    playbackward.graphics.endFill();
    playbackward.graphics.lineStyle( lineWidth, buttonColor, buttonAlpha );
    playbackward.graphics.moveTo( buttonWidth - margin, buttonHeight / 2 );
    playbackward.graphics.lineTo( margin, buttonHeight / 2 );
    playbackward.graphics.lineTo( buttonWidth / 2, margin );
    playbackward.graphics.moveTo( margin, buttonHeight / 2 );
    playbackward.graphics.lineTo( buttonWidth / 2, buttonHeight - margin );
    playbackward.x = 0;
    player.addChild( playbackward );
    playbackward.addEventListener( MouseEvent.CLICK, wm.states.playBackward );

    this.addChild( player );
  }

  private function fillBackground():Void {
    this.graphics.beginFill( bgColor, bgAlpha );
    this.graphics.drawRect( 0, 0, wm.stage.stageWidth, buttonHeight );
    this.graphics.endFill();
    this.alpha = 0.0;
  }

  private function createForwardButton():Void {
    var forward_button = new Sprite();
    forward_button.graphics.beginFill( bgColor, bgAlpha );
    forward_button.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    forward_button.graphics.endFill();

    forward_button.graphics.lineStyle( 0, buttonColor, buttonAlpha );
    forward_button.graphics.beginFill( buttonColor, buttonAlpha );
    forward_button.graphics.moveTo( margin, margin );
    forward_button.graphics.lineTo( margin, buttonHeight - margin );
    forward_button.graphics.lineTo( buttonWidth - margin, buttonHeight / 2 );
    forward_button.graphics.lineTo( margin, margin );
    forward_button.graphics.endFill();
    this.addChild( forward_button );
    forward_button.x = wm.stage.stageWidth - 2 * buttonWidth;
    forward_button.addEventListener( MouseEvent.CLICK, wm.states.forwardScene );
  }

  private function createGoToLastButton():Void {
    var last_button = new Sprite();
    last_button.graphics.beginFill( bgColor, bgAlpha );
    last_button.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    last_button.graphics.endFill();

    last_button.graphics.lineStyle( 0, buttonColor, buttonAlpha );
    last_button.graphics.beginFill( buttonColor, buttonAlpha );
    last_button.graphics.moveTo( margin, margin );
    last_button.graphics.lineTo( margin, buttonHeight - margin );
    last_button.graphics.lineTo( buttonWidth / 2, buttonHeight / 2 );
    last_button.graphics.lineTo( margin, margin );
    last_button.graphics.moveTo( buttonWidth / 2, margin );
    last_button.graphics.lineTo( buttonWidth / 2, buttonHeight - margin );
    last_button.graphics.lineTo( buttonWidth - margin, buttonHeight / 2 );
    last_button.graphics.lineTo( buttonWidth / 2, margin );
    last_button.graphics.endFill();
    this.addChild( last_button );
    last_button.x = wm.stage.stageWidth - buttonWidth;
    last_button.addEventListener( MouseEvent.CLICK, wm.states.gotoLastScene );
  }

  private function createBackButton():Void {
    var back_button = new Sprite();
    back_button.graphics.beginFill( bgColor, bgAlpha );
    back_button.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    back_button.graphics.endFill();

    back_button.graphics.lineStyle( 0, buttonColor, buttonAlpha );
    back_button.graphics.beginFill( buttonColor, buttonAlpha );
    back_button.graphics.moveTo( buttonWidth - margin, margin );
    back_button.graphics.lineTo( buttonWidth - margin, buttonHeight - margin );
    back_button.graphics.lineTo( margin, buttonHeight / 2 );
    back_button.graphics.lineTo( buttonWidth - margin, 2 );
    back_button.graphics.endFill();
    this.addChild( back_button );
    back_button.x = buttonWidth;
    back_button.addEventListener( MouseEvent.CLICK, wm.states.backScene );
  }

  private function createGoToInitButton():Void {
    var init_button = new Sprite();
    init_button.graphics.beginFill( bgColor, bgAlpha );
    init_button.graphics.drawRect( 0, 0, buttonWidth, buttonHeight );
    init_button.graphics.endFill();

    init_button.graphics.lineStyle( 0, buttonColor, buttonAlpha );
    init_button.graphics.beginFill( buttonColor, buttonAlpha );
    init_button.graphics.moveTo( buttonWidth - margin, margin );
    init_button.graphics.lineTo( buttonWidth - margin, buttonHeight - margin );
    init_button.graphics.lineTo( buttonWidth / 2, buttonHeight / 2 );
    init_button.graphics.lineTo( buttonWidth - margin, margin );
    init_button.graphics.moveTo( buttonWidth / 2, margin );
    init_button.graphics.lineTo( buttonWidth / 2, buttonHeight - margin );
    init_button.graphics.lineTo( margin, buttonHeight / 2 );
    init_button.graphics.lineTo( buttonWidth / 2, margin );
    init_button.graphics.endFill();
    this.addChild( init_button );
    init_button.x = 0;
    init_button.addEventListener( MouseEvent.CLICK, wm.states.gotoInitScene );
  }
}
