'use strict';

/*@
Ox.LargeVideoTimeline <f> LargeTimeline Object
    ([options[, self]]) -> <o:Ox.Element> LargeTimeline Object
    options <o> Options object
    self    <o> shared private variable
    position <!> position
@*/

Ox.LargeVideoTimeline = function(options, self) {

    self = self || {};
    var that = Ox.Element({}, self)
            .defaults({
                cuts: [],
                duration: 0,
                find: '',
                getImageURL: null,
                'in': 0,
                matches: [],
                out: 0,
                position: 0,
                subtitles: [],
                type: '',
                width: 0
            })
            .options(options || {})
            .update({
                find: setSubtitles,
                'in': function() {
                    setPointMarker('in');
                },
                out: function() {
                    setPointMarker('out');
                },
                position: setPosition,
                subtitles: setSubtitles,
                type: setType,
                width: setWidth
            })
            .addClass('OxLargeVideoTimeline')
            .mouseleave(mouseleave)
            .mousemove(mousemove)
            .bindEvent({
                anyclick: click,
                dragstart: dragstart,
                drag: drag
            });

    self.$cuts = [];
    self.$pointMarker = {};
    self.$tiles = {};
    self.$tooltip = Ox.Tooltip({animate: false});
    self.center = Math.floor(self.options.width / 2);
    self.fps = 25;
    self.height = 64;
    self.tileWidth = 1500;
    self.tiles = self.options.duration * self.fps / self.tileWidth;

    self.$timeline = $('<div>')
        .css({left: self.center + 'px'})
        .appendTo(that)

    setSubtitles();

    self.options.cuts.forEach(function(v, i) {
        self.$cuts[i] = $('<img>')
            .addClass('OxCut')
            .attr({src: Ox.UI.getImageURL('markerCut')})
            .css({left: (v * self.fps) + 'px'})
            .appendTo(self.$timeline)
    });

    self.$markerPosition = $('<img>')
        .addClass('OxMarkerPosition')
        .attr({src: Ox.UI.getImageURL('markerPosition')})
        .appendTo(that);

    setMarker();

    ['in', 'out'].forEach(function(point) {
        var titlecase = Ox.toTitleCase(point);
        self.$pointMarker[point] = $('<img>')
            .addClass('OxMarkerPoint' + titlecase)
            .attr({src: Ox.UI.getImageURL('marker' + titlecase)})
            .appendTo(self.$timeline);
        setPointMarker(point);
    });

    setWidth();
    setPosition();

    function click(data) {
        self.options.position = Ox.round(Ox.limit(
            getPosition(data), 0, self.options.duration
        ), 3);
        setPosition();
        triggerPositionEvent();
    }

    function dragstart(data) {
        self.drag = {x: data.clientX};
    }

    function drag(data) {
        self.options.position = Ox.round(Ox.limit(
            self.options.position + (self.drag.x - data.clientX) / self.fps,
            0, self.options.duration
        ), 3);
        self.drag.x = data.clientX;
        setPosition();
        triggerPositionEvent();
    }

    function getPosition(e) {
        return self.options.position + (
            e.clientX - that.offset().left - self.center - 1
        ) / self.fps;
    }

    function mouseleave(e) {
        self.clientX = 0;
        self.clientY = 0;
        self.$tooltip.hide();
    }

    function mousemove(e) {
        self.clientX = e.clientX;
        self.clientY = e.clientY;
        updateTooltip();
    }

    function setMarker() {
        self.$markerPosition.css({left: self.center + 'px'});
    }

    function setPointMarker(point) {
        self.$pointMarker[point].css({
            left: (self.options[point] * self.fps) + 'px'
        });
    }

    function setPosition() {
        self.tile = Math.floor(self.options.position * self.fps / self.tileWidth);
        self.$timeline.css({
            marginLeft: (-self.options.position * self.fps) + 'px'
        });
        Ox.loop(
            Math.max(self.tile - 1, 0),
            Math.min(self.tile + 2, self.tiles),
            function(i) {
                if (!self.$tiles[i]) {
                    self.$tiles[i] = $('<img>')
                        .attr({
                            src: self.options.getImageURL(self.options.type, i)
                        })
                        .css({
                            left: (i * self.tileWidth) + 'px'
                        })
                        .appendTo(self.$timeline);
                }
            }
        );
        if (self.clientX && self.clientY) {
            updateTooltip();
        }
    }

    function setSubtitles() {
        that.find('.OxSubtitle').remove();
        self.$subtitles = [];
        self.options.subtitles.forEach(function(subtitle, i) {
            var found = self.options.find
                && subtitle.text.toLowerCase().indexOf(self.options.find.toLowerCase()) > -1;
            self.$subtitles[i] = $('<div>')
                .addClass('OxSubtitle' + (found ? ' OxHighlight' : ''))
                .css({
                    left: (subtitle['in'] * self.fps) + 'px',
                    width: (((subtitle.out - subtitle['in']) * self.fps) - 2) + 'px'
                })
                .html(Ox.highlight(
                    subtitle.text, self.options.find, 'OxHighlight', true
                ))
                .appendTo(self.$timeline);
        });
    }

    function setType() {
        Ox.forEach(self.$tiles, function($tile, i) {
            $tile.attr({src: self.options.getImageURL(self.options.type, i)});
        });
    }

    function setWidth() {
        self.center = Math.floor(self.options.width / 2);
        that.css({
            width: self.options.width + 'px'
        });
        self.$timeline.css({
            left: self.center + 'px'
        });
        setMarker();
    }

    function triggerPositionEvent() {
        that.triggerEvent('position', {position: self.options.position});
    }

    function updateTooltip() {
        var position = getPosition(self);
        if (position >= 0 && position <= self.options.duration) {
            self.$tooltip
                .options({
                    title: Ox.formatDuration(position, 3)
                })
                .show(self.clientX, self.clientY);
        } else {
            self.$tooltip.hide();
        }
    }

    return that;

};
