﻿
/* -----------------------------------------------------------------------------

context.js uses:
  jquery*.js
  jquery-ui*.js ( for dialog )
  inheritance.js
  
------------------------------------------------------------------------------- */

/* -----------------------------------------------------------------------------

Context Class

------------------------------------------------------------------------------- */

var Context = Class.create({

  initialize: function () {

    this.projector = new Projector(this);
    this.slides = {};
    this.currentSlide;
    this.components = {};

    // define event key
    // create state
    // set state to transition table.
    // set default state.

    this.state;
    this.defaultState;
    return true;

  },

  start: function () {

    this.change( this.defaultState );
  
  },

  change: function ( state ) {

    if ( this.state ) {
      this.state.teardown();
    }

    this.state = state;
    this.state.startup();

  },

  notify: function ( key, arg ) {

    var beginState = this.state;
    var res;

    if ( this.state[key] ) {

      res = this.state[key](arg);

    }

    if ( beginState == this.state && this.state != this.state.transit( key ) ) {

      this.change( this.state.transit( key ) );

    }

    return res;

  },

  slided: function ( key ) {

    if ( this.state != this.state.transit( key ) ) {

      this.change( this.state.transit( key ) );

    }

  },

  setSlide: function ( slide ) {

    this.slides[slide.slideId] = slide;
    slide.setContext(this);
    
  },

  setComponent: function ( component ) {

    this.components[component.componentKey] = component;
    component.setContext(this);

  },

  getCurrentSlide: function () {

    return this.currentSlide;

  }

});

/* -----------------------------------------------------------------------------

State Class

------------------------------------------------------------------------------- */

var State = Class.create({

  initialize: function ( context ) {

    this.context = context;
    this.transitions = {};

  },

  transition: function ( key, state ) {

    this.transitions[key] = state;

  },

  transit: function ( key ) {

    if (this.transitions[key]) {

      return this.transitions[key];

    }
    else {

      return this;

    }

  },
 
  startup: function () {

     // state start.
     return true;

  },

  teardown: function () {

     // state is finish.
     return true;

  }

});

/* -----------------------------------------------------------------------------

Projector Class

------------------------------------------------------------------------------- */

var Projector = Class.create({

  initialize: function ( context ) {

    this.slideClassName = "slide";
    this.allSlides = this.getAllSlides();
    this.slides = this.getSlides();
    this.slideKeys = this.getSlideKeys();
    this.slideIds = this.getSlideIds();
    this.currentSlideNum = 0;
    this.pushedSlideNums = [];

    this.floatingWindowClassName = "floatingWindow";
    this.initWindow();
    this.currentWindow;

    this.context = context;

  },

  goto: function ( target ) {

    var slideController;
    slideController = this.context.slides[ this.slideIds[this.currentSlideNum] ];

    if (slideController) {

       slideController.stop();

    }

    if ( target.toString(10).match(/^[0-9]+$/) ) {

      this.gotoNum( target );

    }
    else {

      this.gotoId( target );

    }

    this.context.slided( this.slideKeys[this.currentSlideNum] );

    slideController = this.context.slides[ this.slideIds[this.currentSlideNum] ];

    if (slideController) {

      this.context.currentSlide = slideController;

      slideController.play();

    }

  },

  fromto: function ( from, to ) {

    var target;

    if ( from.toString(10).match(/^[0-9]+$/) ) {
      
      target = parseInt( from ) + parseInt( to );
      this.goto( target );

    }
    else {

      var fromNum = this.getSlideNumById( from );
      target = parseInt(fromNum) + parseInt(to);
      this.goto( target );

    }

  },

  gotoNum: function ( num ) {

    if( num <= this.slides.length ) {
      this.allSlides.hide();
      this.show( this.slides[num] );
      this.currentSlideNum = num;
    }

  },

  gotoId: function ( id ) {

      var num = this.getSlideNumById( id );
      this.gotoNum( num );

  },

  next: function () {

    if ( this.hasNext() ) {

      this.goto( parseInt( this.currentSlideNum ) + 1 );

    }

  },

  prev: function () {

    if ( this.hasPrev() ) {
      this.goto( parseInt( this.currentSlideNum ) - 1 );
    }

  },

  push: function ( target ) {

    this.pushedSlideNums.push( this.currentSlideNum.toString(10) );

    if ( target ) {
    
      this.goto( target );
    
    }

  },

  pop: function () {

    var num = this.pushedSlideNums.pop();

    if ( num ) {

      this.goto( num );

    }

  },

  unshift: function ( target ) {

    this.pushedSlideNums.unshift( this.currentSlideNum.toString(10) );

    if ( target ) {
    
      this.goto( target );
    
    }

  },

  shift: function () {

    var num = this.pushedSlideNums.shift();

    if ( num ) {

      this.goto( num );

    }

  },

  empty: function () {

    this.pushedSlideNums = [];

  },

  show: function ( slide ) {

    slide.show();

  },

  hide: function ( slide ) {

    slide.hide();

  },

  getAllSlides: function () {

    return $("." + this.slideClassName);

  },

  getSlideByNum: function ( num ) {

    return $("." + this.slideClassName + ":eq(" + num + ")");

  },

  getSlideNumById: function ( id ) {
    
    for ( var i in this.slides ) {

      if ( id == this.slides[i].attr("id") ) {
        return i;
        break;
      }

    }

    return true;

  },

  getSlideIdByNum: function ( num ) {

    return this.slides[num].attr("id");

  },

  getSlides: function () {

    var a = [];

    for ( var i = 0; i < this.allSlides.length; i++ ) {
      a[i] = this.getSlideByNum(i);
    }

    return a;

  },

  getSlideKeys: function () {

    var a = [];

    for ( var i = 0; i < this.allSlides.length; i++ ) {
      a[i] = this.slides[i].attr("class").split(" ")[1];
    }

    return a;

  },

  getSlideIds: function () {

    var a = [];

    for ( var i = 0; i < this.allSlides.length; i++ ) {
      a[i] = this.slides[i].attr("id");
    }

    return a;

  },

  hasNext: function () {

    if ( this.currentSlideNum == this.slides.length - 1 ) {
      return false;
    }
    else {
      return true;
    }

  },

  hasPrev: function () {

    if ( this.currentSlideNum == 0 ) {
      return false;
    }
    else {
      return true;
    }

  },

  initWindow: function () {

    $("." + this.floatingWindowClassName).hide();

  },

  openWindow: function ( id, modal, width, height ) {

    if (this.currentWindow ) {

      this.currentWindow.dialog("close");

    }

    var w = $("#" + id);

    var width = width ? width : 300;
    var height = height ? height : 200;

    if (modal) {
      
      this.currentWindow  = w.dialog( { modal:1, overlay: { opacity: 0.5, background: "black" }, width:width, height:height, resizable:false } );
    }
    else {

      this.currentWindow  = w.dialog({ width:width, height:height });

    }

    w.show();

  },

  closeWindow: function () {
    
    this.currentWindow.dialog("close");

  }

});

/* -----------------------------------------------------------------------------

Slide Class

------------------------------------------------------------------------------- */

var Slide = Class.create({

  initialize: function ( slideId ) {

    this.slideId = slideId;
    this.context;

  },

  play: function () {

  },

  stop: function () {

  },

  setContext: function ( context ) {

    this.context = context;

  }

});

/* -----------------------------------------------------------------------------

Component Class

------------------------------------------------------------------------------- */

var Component = Class.create({

  initialize: function ( componentKey ) {

    this.componentKey = componentKey;
    this.context;

  },

  play: function () {

  },

  stop: function () {

  },

  show: function () {

  },

  hide: function () {

  },

  active: function () {

  },

  inactive: function () {

  },

  setContext: function ( context ) {

    this.context = context;

  }

});


