/* global App, Player, Keys, APP_CONFIG */
/* global channels */
/* global $, _, $$nav, $$log, $$error */

(function() {
    "use strict";

    var _inited;

    _.templateSettings.interpolate = /\{\{([\s\S]+?)\}\}/g;
    // var itemHtml = _.template('<li data-index="{{system_name}}" data-number="{{number}}" data-url="{{link}}" data-title="{{title}}" data-preview="{{preview}}" class="channel-item nav-item navigation-item"><img height="96" width="96" src="{{preview}}"/></li>');

	var itemHtml = _.template('<li data-index="{{index}}" data-title="{{name}}" data-url="{{url}}" class="channel-item nav-item navigation-item">{{ii}} {{name}}</li>');
	// var itemHtml = _.template('<li data-index="{{index}}" data-title="{{name}}" data-url="{{url}}" class="channel-item nav-item navigation-item"><div class="icon" style="background-image:url({{icon}})"></div>{{name}}</li>');

  App.scenes.iptv = {
    toString: function() {
        return 'iptv';
    },
    current_index: null,
    program_name: null,
    current_channel_name: null,

    _current_nav_top: 0,

    init: function() {
      _inited = true;
    },

    loadChannels: function(serverConfig) {
      var script = document.createElement('script');
        script.src = App.getApiUrl(APP_CONFIG.IPTV_CHANNELS_URL + '?' + serverConfig.last_modified);
        script.onload = function () {

          $$log('Success channels loaded, count:' + window.channels && window.channels.length);

          App.scenes.iptv.render();
          App.scenes.iptv.show();

          App.loader(false, 'ajax to IPTV_CHANNELS_UPDATES_INFO_URL');
        }
      document.body.appendChild(script);

      // App.localTimeDiff = Date.now() - new Date(info.date + ' ' + info.current_time).getTime() + info.correction_time;
    },

    render: function () {
      this.$el = $('.scene-iptv-content');
      var channels = window.channels;

      // 01. 02. ...
      for (var i=0; i<channels.length; i++) {
      	var chennel = channels[i];
      	chennel.ii = i + 1 + '.';
      }

      this.renderItems(channels);

      this.$el.find('.channel-item').on({
          'nav_focus': this.onChannelFocus,
          'nav_blur': function() {
            App.dispatch(App.legendActions.setInfo(''));
          }
      });

      this.$el.find('.channel-item')
    },

  	onChannelFocus: function (e) {
  		var iptv = window.App.scenes.iptv;
  		var index = $(this).data('index');
  		var program = iptv.getProgram(index);

      // Store focused channel
      App.scenes.current_ch = index;

  		App.scenes.iptv.autoScroll($(this));

  		if (program === undefined) {
  			program = false;
  		}

      iptv.current_program = program;
      iptv.current_channel_name = $(this).data('title');

      // Информация о выбранной программе
      iptv.updateChannelPreview( program )

  		if (program) {
        // Прогресс текущей программы
        iptv.renderProgramProgress( program )
  		}

  		// Почемуто nav_focus перекрывает события ch_up, ch_down и таймер на скрытие меню не обновляется
  		if (App.modules.interfaceOverTv.visible) {
  		  App.modules.interfaceOverTv.updateTimer();
  		}
  	},

    updateChannelPreview: function (program) {
      App.dispatch(App.iptvActions.setChannelName(this.current_channel_name));
      App.dispatch(App.iptvActions.setScreenshotSrc(this.programScreenshotSrc()));

      if (!program) {
        App.dispatch(App.iptvActions.setProgramName(''));

        App.dispatch(App.legendActions.setInfo(''));
        $$log('tv_program : No programm');

        return;
      }

      var time = program.end_time ? program.current_time + ' - ' + program.end_time : program.current_time || '';
      var next_time = program.next_end_time ? program.end_time + ' - ' + program.next_end_time :program.end_time || '';

      App.dispatch(App.iptvActions.setProgramName(program.program_name));
      App.dispatch(App.iptvActions.setTime(time));
      App.dispatch(App.iptvActions.setDesc(program.desc));
      App.dispatch(App.iptvActions.setNextTitle(program.next_title));
      App.dispatch(App.iptvActions.setNextTime(next_time));

      App.dispatch(App.legendActions.setInfo('tv_program'));
      $$log('tv_program : On');
    },

    //
    channelNameHtml: function () {
      return '<h4>' + this.current_channel_name + '</h4>';
    },

    programScreenshotSrc: function () {
      var channel = window.channels[ App.scenes.current_ch ];
      var url = channel.url;
      var name = url.replace(/.*\/(.*?)/gi, '$1') + '.jpg';
	    var nocache = '?' + Date.now();

      return App.getApiUrl(APP_CONFIG.IPTV_SCREENSHOT_PATH + name + nocache);
    },

    // Прогресс текущей программы
    renderProgramProgress: function ( program ) {
      if (program.progress === false) {
        return;
      }
      var width = program.progress * 100; // 100px max
      if (!$(".program-progress").html()) {
        $(".program-progress").html(
          "<div class='program-progress-bg'><i/><i/><i/><i/><i/><i/><i/><i/><i/><i/></div>"+
          "<div class='program-progress-fg' style='width:"+width+"px'><i/><i/><i/><i/><i/><i/><i/><i/><i/><i/></div>"
        );
      }
    },

		autoScroll: function ($item) {
			if (!_inited) return;

			var $list = this.$el.find('.navigation-items'),
				itemTop = $item.position().top,
				$lastItem = $list.find('li').last(),
				minFocusPosition = 0,
				maxFocusPosition = $list.parent().height() - $item.height()*2,
				isMoveUp = this._current_nav_top > itemTop,
				isMoveDown = this._current_nav_top < itemTop;

			if (itemTop < minFocusPosition && isMoveUp || $item[0] == $lastItem[0]) {
				$list[0].insertBefore($lastItem[0], $list.find('li')[0]);
			} else if (itemTop > maxFocusPosition && isMoveDown) {
				$list.find('li').first().appendTo($list);
			}

			this._current_nav_top = $item.position().top; // обновленный top после dom-change
		},

    // открытие сохранненого канала или первого в списке
    autoOpenChannel: function () {
      this.setNavCurrent(window.App.scenes.current_ch || 0);
    },

    /**
     * Manual change channels navigation selection
     */
    setNavCurrent: function (index) {
      App.scenes.current_ch = index;
      $$nav.current( $(".navigation-items li[data-index="+index+"]:first") )
    },

    show: function(keyset) {
        var iptv = this;

        if (!_inited) {
            this.init();
            return;
        }

        this.$el.show();

        // TODO: чего-то проигрывание программ перестало работать, проверить в localhost?

        // keys for this scene
        Keys.set( keyset || 'iptv' );

        $('li[data-scene=iptv]').addClass('active');

		    // Анимация
        $('.menu').stop().show().animate({
          left: 0,
          opacity: 1
        });

        $('.channel-preview')
          .css({ opacity: 1 }) // Восстанавливается интерфейс если сцену переоткрыли во время просмотра TV
          .show();

        $('#channelPreview');

        setTimeout(function () {
          // Включить навигацию
          $$nav.on();

          // Возвращать фокус на первый канал при переходе в IPTV
          iptv.autoOpenChannel();
        }, 0);
    },

    // handler for click event
    // TODO: сделать общим событием через document.on что бы перенести в keys, это необходимо для того что-бы управлять режимом видео
    onEnterClick: function(e) {
      var $focus = $('.scene_iptv .navigation-items .focus');
      var index = $focus.attr('data-index');

  	  // По каким-то причинам происходит вызов события при переходе из настроек в IPTV
  	  if (!index) {
    		return;
  	  }

      App.scenes.iptv.playChannel(index);

      e.stopPropagation();
    },

    renderItems: function(items) {
        var html = '';

        $('li[data-scene=iptv]').text('IPTV (' + items.length + ')');

        for (var i = 0, len = items.length; i < len; i++) {
          var itemId = items[i].id;
          var iconUrl = App.getApiUrl(APP_CONFIG.IPTV_ICONS_URL + itemId + '.gif');

  				items[i].index = i;
  				items[i].icon = itemId ? iconUrl : '';

          html += itemHtml(items[i]);
        }

        this.$el.find('.navigation-items')
                .empty()
                .html(html);
    },

    // Информация о текущей программе канала с индексом index
    getProgram: function(index) {
			var channel = channels[index],
				programs = channel.list;

			if (!programs) {
				return null;
			}

      var programTimeUtils = App.scenes.program;

  		var shift = (channel.shift || 0) *60*60*1000,
          now = new Date().getTime();

  		var start_time = Date.now();
  		var end_time;
  		var next_title;
      var next_end_time;
      var progress;
  		var program;
      var programIndex = 0;

  		for (var i=0; i<programs.length; i++) {
  			var checkProgram = programs[i],
            programTime = programTimeUtils.getTime(checkProgram.start) - shift,
            programDate = new Date( programTime );

  			if (now > programTime) {
  				program = checkProgram;
  				start_time = programDate;
          programIndex = i;
  			} else if (!end_time) {
  				end_time = programDate;
  				next_title = checkProgram.title;
          progress = 1 - (programTime - now) / (programTime - start_time.getTime());
  			} else if (!next_end_time) {
          next_end_time = programTimeUtils.toLocalTime( programDate );
          break;
        }
  		}

  	if (!program) {
  		$$error('Not found programm for ' + channel.name);
  		return;
  	}

  	// Если программа > 24 часа, то устарела
  	if (now - start_time > 1000*60*60*24) {
  		program.desc = App.t('tv_program_old');
  	}

  	// Смещение время программы на настройки локального времени
    start_time = programTimeUtils.toLocalTime( start_time );
    end_time = programTimeUtils.toLocalTime( end_time );

    if (!start_time) {
  		$$('null start_time ' + channel.name + ' ' + program.title + ' ' + program.start);
  	}

  	// console.log(listDate, program);
  	return program ? {
      progress: progress,
  		program_name: program.title,
  		current_time: programTimeUtils.formatTime(start_time),
  		end_time: programTimeUtils.formatTime(end_time),
  		next_title: next_title,
      next_end_time: programTimeUtils.formatTime(next_end_time),
  		desc: program.desc,
      index: programIndex,
  	} : {
  		program_name: channel.name
  	};
  },

  returnFromView: function() {

  },

  eachChanel: function(index) {
      var result = null;
      $.each(this.$el.find('.navigation-items li'), function(i, v) {
          if ($(v).data('index') == index)
          {
              result = i;
          }
      });
      return result;
  },

  findChannelByNum: function(num) {
      var result = null;
      $.each(this.$el.find('.navigation-items li'), function(i, v) {
          if ($(v).data('number') == num)
          {
              result = i;
          }
      });
      return result;
  },

  nextChannel: function() {
    var $chanel = this.getCurrentChannelItem();
    var $next = $chanel.next();

    if (!$next[0]) {
      var $first = $chanel.parent().children().first();
      this.playChannel($first.attr('data-index'));
      return;
    }

    this.playChannel($next.attr('data-index'));
  },

  previosChannel: function()
  {
    var $chanel = this.getCurrentChannelItem();
    var $prev = $chanel.prev();

    if (!$prev[0]) {
      var $last = $chanel.parent().children().last();
      this.playChannel($last.attr('data-index'));
      return;
    }

    this.playChannel($prev.attr('data-index'));
  },

  getCurrentChannelItem: function() {
    return $('.channel-item[data-index="'+(this.current_index || 0)+'"]');
  },

  numChanel: function(num) {
// TODO: ...
      console.log('play ' + num);
      var current_ch = App.scenes.iptv.findChannelByNum(num);
      console.log(current_ch);
      if (channels.channels[current_ch] != undefined)
      {
          App.scenes.iptv.playChannel(current_ch);
      }
  },

  playChannel: function (index) {
    this.current_index = index;

		var url = $('.channel-item[data-index="'+index+'"]').attr('data-url');

		if (localStorage) {
			localStorage.setItem('iptv-index', index);
		}

    App.modules.interfaceOverTv.hide();

    App.loader(App.t('buffering'));

    Keys.set('iptv_view');

    Player.play({
      url: url + '?token=' + APP_CONFIG.IPTV_TOKEN,
      type: 'vod',
      onerror: App.scenes.iptv.onVideoError,
      iptv: true,
    });
	},

  onVideoError: function () {
    App.error('video_error', function(){
        App.scenes.iptv.exitPlayVideoView();
    });
  },

  exitPlayVideoView: function () {
    $('#chanel-info').hide();

    if (Player.state === 'play')
    {
        App.loader(false, 'iptv::exitPlayVideoView');

        Player.stop();
    }

    App.$errorModal.hide();
    $$nav.restore();

    // window.App.toggleView();
    this.show();
    window.Keys.set('iptv');

    $('#version').show();
    $('#channelPreview').stop().animate({ opacity: 1 });
  },

	// если открыть канал, то потом пропадает меню пока навигация по верхнему меню
	onMainMenuFocus: function () {
	  if (App.modules.interfaceOverTv.visible) {
      App.modules.interfaceOverTv.updateTimer();
	  }
	},

  	hide: function() {
      this.$el.hide();

  	  $$log('iptv.hide()');

  	  // если открыть канал, то потом пропадает меню
      App.modules.interfaceOverTv.stopTimer();

  	  // TODO: возможно вызвать прекращение проигрывания?

      $('li[data-scene=iptv]').removeClass('active');

      $('.channel-preview').hide();
    }

  };

})();
