Interface = Class.create(TransitionManager, {
  canSupportFlash: false,
  supportsFlash: false,
  flashContentDimensions: {width: 1200, height: 586},
  autoPlay: true,
  flashVars: {},

  initialize: function($super, autoPlay, flashVars) {
    this.autoPlay = autoPlay;
    if (!Prototype.Browser.MobileSafari) this.canSupportFlash = true;
    if (this.canSupportFlash) {
      this.supportsFlash = SwfInstance.hasPlayerVersion('10.0.0');
      this.flashVars = flashVars;
    }

    // tell css what we can do
    Utility.addHTMLClassName('with-javascript' + (this.supportsFlash ? ' with-flash' : ''));

    // draw the page
    this.drawPage();
    Font.now();

    // setup the transition manager to observe any anchors and/or forms we want
    $super({anchors: ['logo', 'html_content'], forms: ['subdealer_locator', 'html_content']});
  },

  /* Sets up the page by creating any objects that should be created, and other
   * misc display tasks.
   */
  drawPage: function() {
    // display the upgrade message if we should
    if (this.canSupportFlash && !this.supportsFlash) this.showUpgradeMessage();
    if (this.supportsFlash) {
      this.loadBackgroundSwf();
      this.player = new Player('music_player_container', this.autoPlay);
    } else {
      var backgroundImage = $('flash_content').down('.background-image');
      backgroundImage.setAttribute('src', backgroundImage.getAttribute('alt'));
      this.handleWindowResize();
    }

    this.navigation = new Navigation('navigation');
    this.finalizePage();
  },

  finalizePage: function() {
    this.shareForm = new ShareForm('share_form');
    this.makeHelperInputs();
    this.makeTextareasLimitInput();
  },

  /* Loads the background swf and passes the flash vars along to the flash.
   */
  loadBackgroundSwf: function() {
    this.backgroundSwf = new BackgroundSwf(
      'site/flash/background.swf?' + Math.floor(Math.random() * 1000000),
      'flash_background', '100%', '1', '9.0.115',
      this.flashVars,
      {wmode: 'opaque'},
      {allowscriptaccess: 'always'}
    );
  },

  /* Displays a mask in front of the body that obscures it a little.  Also sets
   * a window resize observer to keep it the right size all the time.
   */
  mask: function() {
    if (!this._maskWindowObserver) {
      this._maskWindowFunction = this.mask.bindAsEventListener(this);
      this._maskWindowObserver = Event.observe(window, 'resize', this._maskWindowFunction);
    }
    $('body_mask').setStyle({height: document.viewport.getHeight() + 'px', display: 'block'});
  },

  /* Removes the mask that can be in front of the body.
   */
  unMask: function() {
    if (this._maskWindowObserver) {
      Event.stopObserving(window, 'resize', this._maskWindowFunction);
      this._maskWindowObserver = null;
    }
    $('body_mask').hide();
  },

  /* Shows an upgrade message -- typically when the client is capible of
   * displaying flash, but doesn't have it available.
   */
  showUpgradeMessage: function() {
    var upgrade = $('upgrade');
    if (upgrade) upgrade.setStyle({display: 'block'});
  },

  /* Function that simply replaces a form (needed because firefox was weird)
   */
  replaceForm: function(element, content) {
    element = $(element);
    if (!element) return;

    element.replace(content);

    this.makeHelperInputs();
  },

  /* Makes input fields with the class name "helper" have a default value that
   * will clear itself for user input, and fills the helper text back when the
   * input loses focus while empty.
   */
  makeHelperInputs: function(element) {
    element = $(element);

    var helpers = [];
    if (element) helpers = element.select('input.helper');
    else helpers = $$('input.helper');

    helpers.each(function(input) {
      if (!input.title || input._helper) return;
      input._helper = true;

      var form = input.up('form');
      if (form) form.observe('submit', function() { if (input.value == input.title) input.value = ''; });

      if (!input.value) input.value = input.title;
      else input.removeClassName('helper');

      input.observe('focus', function() {
        if (input.value == input.title) {
          input.value = '';
          input.removeClassName('helper');
        }
      });

      input.observe('blur', function() {
        if (!input.value) {
          input.value = input.title;
          input.addClassName('helper');
        }
      });
    });
  },

  /* Makes all textareas with a "limited" class limit the number of characters
   * that are allowed to be entered in it.  It will update the number of chars
   * left in a given textarea with the [textarea.id]_counter id set on it.  The
   * number of characters it will restrict to is pulled from the title, so if
   * you want a 200 char limit, put something like "200 character limit" in the
   * title attribute (defaults to 100 if unable to parse one).
   */
  makeTextareasLimitInput: function() {
    $$('textarea.limited').each(function(textarea) {
      var element = textarea, limit = parseInt(element.title) || 100;
      var counter = (element.id) ? $(element.id + '_counter') : false;
      var limitInput = function(event) {
        if (element.value.length > limit) element.value = element.value.substring(0, limit);
        if (counter) {
          var charsLeft = (limit - element.value.length);
          counter.update(charsLeft + ((charsLeft == 1) ? ' character ' : ' characters ') + 'left');
          if (charsLeft) counter.removeClassName('max-reached');
          else counter.addClassName('max-reached');
        }
      }
      $w('keyup keydown blur').each(function(eventName) {
  			textarea.observe(eventName, limitInput, false);
      });
    });
  },

  /* This function used as a window resize observer, so every time the window is
   * resized, this function is called -- only when flash is not enabled.
   */
  handleWindowResize: function() {
    var flashContent = $('flash_content');
    var backgroundImage = flashContent.down('.background-image');

    var imageRatio = this.flashContentDimensions.width / this.flashContentDimensions.height;
    var containerDimensions = flashContent.getDimensions();
    var bodyRatio = containerDimensions.width / containerDimensions.height;

    var width = 0;
    var height = 0;
    if (imageRatio <= bodyRatio) {
      width = containerDimensions.width
      height = containerDimensions.width / imageRatio;
    } else {
      height = containerDimensions.height;
      width = containerDimensions.height * imageRatio;
    }

    backgroundImage.setStyle({width: width + 'px', height: height + 'px'});

    if (!this._handleWindowResizeEvent) {
      this._handleWindowResizeEvent = Event.observe(window, 'resize', this.handleWindowResize.bindAsEventListener(this));
    }
  },

  /* Transitions one page to another page using animations.  Is event driven,
   * and expects a url in the event.memo.  Fire interface:transition on the
   * document to transition from one page to another.
   */
  transition: function(event) {
    var options = (event.memo) ? event.memo : {};
    if (!options['url'] || document._transitioning) return;

    window.location.href = TransitionManager.makeUrlForHash(options['url'], window.location.href);
    window.currentLocation = window.location.href;

    var urlParts = TransitionManager.getUrlParts(options['url']);
    var toolbarLink = $('rta_toolbar_link');
    if (toolbarLink) toolbarLink.href = '?wedit=true&' + urlParts.query;

    document._transitioning = true;
    document.body.addClassName('transitioning');

    if (options['transitionType']) {
      this[options['transitionType'].replace('transition:', '') + 'TransitionOut'](options);
    } else {
      this.defaultTransitionOut(options);
    }
  },

  productTransitionOut: function(options) {
    document.body.addClassName('loading');
    new Ajax.Request(options['url'], {
      parameters: options['params'],
      method: (options['method']) ? options['method'] : 'get',
      onSuccess: function(transport) {
        var response = transport.responseJSON;
        trace('response', response);

        // tracking
        try {
          trace('tracking');
          var pageTracker = _gat._getTracker('UA-9601415-1');
          pageTracker._trackPageview();
        } catch(e) {
          trace(e);
        }

        document.body.removeClassName('loading');

        // load the new content in
        document.title = response['browser_title'];
        $('content_container').innerHTML = response['content'] + '<div class="clear">';
        response['content'].evalScripts();

        if (this.supportsFlash) {
          this.backgroundSwf.loadSection(response['display_title'] != '0' ? response['page_title'] : '', response['background'], false, false);
          if (response['product_images']) this.backgroundSwf.showProduct(response['product_images'][0], response['product_images'][1]);
          this.player.toggle(response['stops_music']);
        } else {
          setTimeout(this.transitionIn.bind(this), 500);
        }
        this.finalizePage();
        this.navigation.selectFromPath(response['navigation']);
        this.observeAnchorsFor(['html_content']);
        this.observeFormsFor(['html_content']);
        Cufon.refresh();
        document._transitioning = false;
        document.body.removeClassName('transitioning');
      }.bind(this),
      onFailure: function() {
        alert("Oh, heavens!  We're unable to load the page.. was the connection to the server lost?");
        document._transitioning = false;
        document.body.removeClassName('transitioning');
      }
    });
  },

  defaultTransitionOut: function(options) {
    new Effect.ScrollTo($('control'), { duration: 0.01 });
    new Effect.Parallel([
      new Effect.Morph($('flash_content'), { style: {height: '0px'} }),
      new Effect.Opacity($('content_container'), { from: 1, to: 0 })
    ], {
      transition: Effect.Transitions.easeFromTo,
      duration: .75,
      afterFinish: function() {
        document.body.addClassName('loading');
        new Ajax.Request(options['url'], {
          parameters: options['params'],
          method: (options['method']) ? options['method'] : 'get',
          onSuccess: function(transport) {
            var response = transport.responseJSON;
            trace('response', response);

            // tracking
            try {
              trace('tracking');
              var pageTracker = _gat._getTracker('UA-9601415-1');
              pageTracker._trackPageview();
            } catch(e) {
              trace(e);
            }

            document.body.removeClassName('loading');

            // load the new content in
            document.title = response['browser_title'];
            $('content_container').innerHTML = response['content'] + '<div class="clear">';
            response['content'].evalScripts();

            if (this.supportsFlash) {
              this.backgroundSwf.loadSection(response['display_title'] != '0' ? response['page_title'] : '', response['background'], false, true, this.transitionIn.bind(this));
              if (response['product_images']) this.backgroundSwf.showProduct(response['product_images'][0], response['product_images'][1]);
              this.player.toggle(response['stops_music']);
            } else {
              setTimeout(this.transitionIn.bind(this), 500);
            }
            this.finalizePage();
            this.navigation.selectFromPath(response['navigation']);
            this.observeAnchorsFor(['html_content']);
            this.observeFormsFor(['html_content']);
            Cufon.refresh();
          }.bind(this),
          onFailure: function() {
            alert("Oh, heavens!  We're unable to load the page.. was the connection to the server lost?");
            document._transitioning = false;
            document.body.removeClassName('transitioning');
          }
        });
      }.bind(this)
    });
  },

  transitionIn: function() {
    new Effect.Morph($('flash_content'), {
      style: {height: '586px'},
      transition: Effect.Transitions.easeFromTo,
      duration: .75,
      afterFinish: function() {

        // show the title
        if (this.supportsFlash) this.backgroundSwf.showTitle();

        new Effect.Opacity($('content_container'), {
          from: 0,
          to: 1,
          duration: .25,
          afterFinish: function() {
            document._transitioning = false;
            document.body.removeClassName('transitioning');
          }
        });
      }.bind(this)
    });
  }

});
