(function($, s4ntc){

  s4ntc.vem = {};

  s4ntc.vem.VemPlayer = function(vemViewport, vemController, options) {
    this._vemViewport = vemViewport;
    this._vemController = vemController;
    this._options = $.extend(true, {}, options);
  };

  s4ntc.vem.VemController = function(vemEngine, vemViewport, playerClass, options) {
    this._vemEngine = vemEngine;
    this._vemViewport = vemViewport;
    this._playerClass = playerClass;
    this._playerOptions = options;
    this._player = null;
  };
  s4ntc.vem.VemController.prototype.createPlayer = function() {
    return (this._player = new this._playerClass(this._vemViewport, this, this._playerOptions));
  };
  s4ntc.vem.VemController.prototype.getPlayer = function() {
    return this._player !== null ? this._player : this.createPlayer();
  };
  s4ntc.vem.VemController.prototype.globalEvent = function(event_name, event_args) {
    this._vemEngine.globalEvent(this._vemViewport._name, event_name, event_args);
  };
  s4ntc.vem.VemController.prototype.playerEvent = function(event_name, event_args) {
    this._vemViewport.playerEvent(event_name, event_args);
  };
  

  s4ntc.vem.VemViewport = function(name, selector) {
    this._name = name;
    this._selector = selector;
    this._element = $(selector);
    this._player = null;
    this._controller = null;
  };

  s4ntc.vem.VemViewport.prototype.loadPlayer = function(vemEngine, playerClass, options, controllerClass) {
    this._controller = controllerClass !== undefined ? new controllerClass(vemEngine, this, playerClass, options) : new s4ntc.vem.VemController(vemEngine, this, playerClass, options);
    this._player = this._controller.getPlayer();
    return this._player;
  };

  s4ntc.vem.VemViewport.prototype.playerEvent = function(event_name, event_args) {
    //console.log(['listen to '+this._name, event_name, event_args]);
    this._element.trigger(event_name, event_args);
  };

  var vemDefaults = {
    lang: 'it',
    hubselector: '#vem_main_container',
    urls: {},
    viewports: {
      'map': {
        name: 'map',
        selector: '#vem_map_viewport'
      },
      'vtour': {
        name: 'vtour',
        selector: '#vem_vtour_viewport'
      },
      'desc': {
        name: 'desc',
        selector: '#vem_desc_viewport'
      },
      'media': {
        name: 'media',
        selector: '#vem_media_viewport'
      },
      'search': {
        name: 'search',
        selector: '#vem_search_viewport'
      }
    }
  };

  s4ntc.vem.Vem = function(options) {
    this._options = $.extend(true, {}, vemDefaults, options);

    this._hub = $(this._options.hubselector);
    
    this._viewports = {};

    for(var vidx in this._options.viewports) {
      var vopt = this._options.viewports[vidx];
      this._viewports[vopt.name] = new s4ntc.vem.VemViewport(vopt.name, vopt.selector);
    }
  };

  s4ntc.vem.Vem.prototype.PLAYERS = {};
  s4ntc.vem.Vem.prototype.CONTROLLERS = {};

  s4ntc.vem.Vem.prototype.loadPlayer = function(viewport_name, player_name, options) {
    if(this._viewports[viewport_name] == null) {
      throw ['[s4ntc.vem.Vem.loadPlayer] ','Wrong viewport name "',viewport_name,'".'].join('');
    }

    var playerClass = s4ntc.vem.Vem.prototype.PLAYERS[player_name];
    var controllerClass = s4ntc.vem.Vem.prototype.CONTROLLERS[player_name];

    return this._viewports[viewport_name].loadPlayer(this, playerClass, options, controllerClass);
  };

  s4ntc.vem.Vem.prototype.getKrpanoViewReferenceMap = function(krpano_view_id, onSuccess) {
    var url = this.urlFor('vtour_ref_map', {
      id: krpano_view_id
    });
    $.ajax({
      type: 'POST',
      url: url,
      dataType: 'json',
      success: onSuccess
    });
  };

  s4ntc.vem.Vem.prototype.getKrpanoView = function(krpano_view_id, onSuccess) {
    var url = this.urlFor('krpano_view', {
      'lang' : this._options.lang,
      'id' : krpano_view_id
    });
    $.ajax({
      type: 'POST',
      url: url,
      dataType: 'json',
      success: onSuccess
    });
  };

  s4ntc.vem.Vem.prototype.getMedia = function(media_id, onSuccess) {
    var url = this.urlFor('media', {
      'lang' : this._options.lang,
      'id' : media_id
    });
    $.ajax({
      type: 'POST',
      url: url,
      dataType: 'json',
      success: onSuccess
    });
  };

  s4ntc.vem.Vem.prototype.globalEvent = function(viewport_name, event_name, event_args) {
    console.log('global', arguments);
    if(arguments.length == 2) {
      event_args = event_name;
      event_name = viewport_name;
      viewport_name = 'global';
    }
    this._hub.trigger([viewport_name,event_name].join('_'), event_args);
  };

  s4ntc.vem.Vem.prototype.bindGlobalEvent = function(viewport_name, event_name, callback) {
    if(arguments.length == 2) {
      callback = event_name;
      event_name = viewport_name;
      viewport_name = 'global';
    }
    this._hub.bind([viewport_name,event_name].join('_'), callback);
  }

  s4ntc.vem.Vem.prototype.urlFor = function(url_name, params) {
    var url = '';
    if(this._options.urls[url_name] !== undefined) {
      url = this._options.urls[url_name];
      for(var param_name in params) {
        var substitution = ['__',param_name,'__'].join('');
        url = url.replace(substitution, params[param_name]);
      }
    }
    return url;
  };

  s4ntc.vem.Vem.prototype.changeLanguage = function(culture) {
    if( this._options.lang !== culture ) {
      this._options.lang = culture;
      this.globalEvent('language_changed', [culture]);
    }
  };


})(jQuery, window.s4ntc !== undefined ? window.s4ntc : (window.s4ntc = {}));
