// vim: et:ts=4:sw=4:sts=4:ft=js

/*@
Ox.VideoPanelPlayer <f:Ox.Element> VideoPanelPlayer Object
    () ->              <f> VideoPanelPlayer Object
    (options) ->       <f> VideoPanelPlayer Object
    (options, self) -> <f> VideoPanelPlayer Object
    options <o> Options object
    self    <o> shared private variable
@*/

Ox.VideoPanelPlayer = function(options, self) {

    var self = self || {},
        that = new Ox.Element({}, self)
            .defaults({
                annotationsSize: 256,
                duration: 0,
                height: 0,
                loop: false,
                muted: false,
                paused: false,
                playInToOut: false,
                points: [0, 0],
                position: 0,
                poster: '',
                showAnnotations: true,
                showControls: true,
                subtitles: [],
                videoHeight: 0,
                videoSize: 'fit',
                videoWidth: 0,
                videoURL: '',
                width: 0
            })
            .options(options || {})
            .css({
                height: self.options.height + 'px',
                width: self.options.width + 'px'
            })
            .bindEvent({
                resize: resizeElement,
                key_shift_a: function() {
                    that.toggleAnnotations();
                },
                key_shift_c: function() {
                    that.toggleControls();
                },
                key_shift_s: function() {
                    that.toggleSize();
                },
                key_space: function() {
                    that.togglePlay();
                }
            });

    $.extend(self, {
        fullscreen: false,
        videoCSS: getVideoCSS()
    });
    //alert(JSON.stringify([self.playerHeight, self.playerWidth, self.videoCSS]))

    self.$player = new Ox.Element()
        .css({
            overflowX: 'hidden',
            overflowY: 'hidden'
        })
        .bind({
            mousedown: that.gainFocus
        })
        .bindEvent({
            resize: resizeVideo
        });

    self.$video = new Ox.VideoElement({
            height: self.videoCSS.height,
            paused: true,
            points: self.options.points,
            position: self.options.position,
            url: self.options.videoURL,
            width: self.videoCSS.width
        })
        .css(self.videoCSS)
        .bindEvent({
            paused: paused,
            playing: playing
        })
        .appendTo(self.$player);

    self.$controls = new Ox.Element()
        .bindEvent({
            toggle: toggleControls
        });

    self.$buttons = new Ox.Element()
        .css({
            float: 'left',
            width: '16px',
            margin: '4px'
        })
        .appendTo(self.$controls);

    self.$button = {
        play: new Ox.Button({
                id: 'play',
                title: [
                    {id: 'play', title: 'play'},
                    {id: 'pause', title: 'pause'}
                ],
                tooltip: ['Play', 'Pause'],
                type: 'image'                
            })
            .bindEvent({
                click: self.$video.togglePlay
            }),
        mute: new Ox.Button({
                id: 'mute',
                title: [
                    {id: 'mute', title: 'mute'},
                    {id: 'unmute', title: 'unmute'}
                ],
                tooltip: ['Mute', 'Unmute'],
                type: 'image'                
            })
            .bindEvent({
                click: self.$video.toggleMute
            }),
        size: new Ox.Button({
                id: 'size',
                title: self.options.videoSize == 'fit' ? [
                    {id: 'fill', title: 'fill'},
                    {id: 'fit', title: 'fit'}
                ] : [
                    {id: 'fit', title: 'fit'},
                    {id: 'fill', title: 'fill'}
                ],
                tooltip: self.options.videoSize == 'fit' ? [
                    'Fill Screen', 'Fit to Screen'
                ] : [
                    'Fit to Screen', 'Fill Screen'
                ],
                type: 'image'
            })
            .bindEvent({
                click: toggleSize
            }),
        fullscreen: new Ox.Button({
                id: 'size',
                title: [
                    {id: 'grow', title: 'grow'},
                    {id: 'shrink', title: 'shrink'}
                ],
                tooltip: [
                    'Enter Fullscreen', 'Exit Fullscreen'
                ],
                type: 'image'
            })
            .bindEvent({
                click: toggleFullscreen
            })
    }
    var i = 0;
    Ox.forEach(self.$button, function($button) {
        $button.css({
            position: 'absolute',
            left: '8px',
            top: (8 + i++ * 24) + 'px'
        })
        .appendTo(self.$buttons);
    });

    self.$timelines = new Ox.Element()
        .css({
            float: 'left',
            margin: '4px'
        })
        .appendTo(self.$controls);

    self.$timeline = {
        large: new Ox.LargeTimeline({
                duration: self.options.duration,
                position: self.options.position,
                subtitles: self.options.subtitles,
                videoId: self.options.videoId,
                width: getTimelineWidth()
            })
            .css({
                top: '4px'
            })
            .bindEvent({
                change: changeLargeTimeline
            }),
        small: new Ox.SmallTimeline({
                duration: self.options.duration,
                position: self.options.position,
                subtitles: self.options.subtitles,
                videoId: self.options.videoId,
                width: getTimelineWidth()
            })
            .css({
                top: '76px'
            })
            .bindEvent({
                change: changeSmallTimeline
            })
    };
    Ox.forEach(self.$timeline, function($timeline) {
        $timeline.appendTo(self.$timelines);
    });

    self.$panel = new Ox.SplitPanel({
            elements: [
                {
                    element: self.$player
                },
                {
                    collapsed: !self.options.showControls,
                    collapsible: true,
                    element: self.$controls,
                    size: 104
                }
            ],
            orientation: 'vertical'
        })
        .bindEvent({
            resize: resizePanel
        });

    self.$annotations = new Ox.Element()
        .bindEvent({
            resize: resizeAnnotations,
            resizeend: resizeendAnnotations,
            toggle: toggleAnnotations
        });

    that.$element = new Ox.SplitPanel({
            elements: [
                {
                    element: self.$panel
                },
                {
                    collapsed: !self.options.showAnnotations,
                    collapsible: true,
                    element: self.$annotations,
                    resizable: true,
                    resize: [192, 256, 320, 384],
                    size: self.options.annotationsSize
                }
            ],
            orientation: 'horizontal'
        });

    function changeLargeTimeline(event, data) {
        self.options.position = data.position;
        self.$video.position(self.options.position);
        self.$timeline.small.options({
            position: self.options.position
        });            
    }

    function changeSmallTimeline(event, data) {
        self.options.position = data.position;
        self.$video.position(self.options.position);
        self.$timeline.large.options({
            position: self.options.position
        });            
    }

    function getPlayerHeight() {
        return self.options.height -
            self.options.showControls * 104 - 1;
    }

    function getPlayerWidth() {
        return self.options.width -
            (self.options.showAnnotations && !self.fullscreen) *
            self.options.annotationsSize - 1;
    }

    function getTimelineWidth() {
        return self.options.width -
            (self.options.showAnnotations && !self.fullscreen) *
            self.options.annotationsSize - 40
    }

    function getVideoCSS() {
        var width = getPlayerWidth(),
            height = getPlayerHeight(),
            ratio = width / height,
            videoRatio = self.options.videoWidth / self.options.videoHeight,
            isWide = ratio < videoRatio;
        return self.options.videoSize == 'fit' ? {
            position: 'absolute',
            left: 0,
            right: 0,
            top: 0,
            bottom: 0,
            width: (isWide ? width : Math.round(height * videoRatio)) + 'px',
            height: (isWide ? Math.round(width / videoRatio) : height) + 'px',
            margin: 'auto'
        } : {
            width: (isWide ? Math.round(height * videoRatio) : width) + 'px',
            height: (isWide ? height : Math.round(width / videoRatio)) + 'px',
            margin: [
                isWide ? '0' : Math.floor((height - width / videoRatio) / 2) + 'px',
                isWide ? Math.ceil((width - height * videoRatio) / 2) + 'px' : '0',
                isWide ? '0' : Math.ceil((height - width / videoRatio) / 2) + 'px',
                isWide ? Math.floor((width - height * videoRatio) / 2) + 'px' : '0'
            ].join(' ')
        };
    }

    function paused() {
        
    }

    function playing(event, data) {
        self.options.position = data.position;
        self.$timeline.large.options({
            position: self.options.position
        });
        self.$timeline.small.options({
            position: self.options.position
        });
    }

    function resizeAnnotations(event, data) {
        self.options.annotationsSize = data;
        resizeVideoAndControls();
    }

    function resizeendAnnotations(event, data) {
        self.options.annotationsSize = data;
        that.triggerEvent('change', {
            annotationsSize: self.options.annotationsSize
        });
    }

    function resizeControls() {
        self.$timeline.large.options({
            width: getTimelineWidth()
        });
        self.$timeline.small.options({
            width: getTimelineWidth()
        });
    }

    function resizeElement(event, data) {
        // called on browser toggle
        self.options.height = data;
        resizeVideo();
    }

    function resizePanel(event, data) {
        // called on annotations toggle
        resizeVideoAndControls();
    }

    function resizeVideoAndControls() {
        resizeVideo();
        resizeControls();
    }

    function resizeVideo() {
        self.videoCSS = getVideoCSS();
        self.$video.css(self.videoCSS);
    };

    function toggleAnnotations(event, data) {
        self.options.showAnnotations = !data.collapsed;
        that.triggerEvent('change', {
            showAnnotations: self.options.showAnnotations
        });
    }

    function toggleControls(event, data) {
        self.options.showControls = !data.collapsed;
        that.triggerEvent('change', {
            showControls: self.options.showControls
        });
    }

    function toggleFullscreen() {
        self.fullscreen = !self.fullscreen;
        self.options.showAnnotations && that.$element.toggle(1);
        self.fullscreen && self.options.showControls && self.$panel.toggle(1);
        that.triggerEvent((self.fullscreen ? 'enter' : 'exit') + 'fullscreen', {});
    }

    function toggleSize() {
        self.options.videoSize = self.options.videoSize == 'fit' ? 'fill' : 'fit';
        resizeVideo();
        that.triggerEvent('change', {
            videoSize: self.options.videoSize
        });
    }

    self.setOption = function(key, value) {
        if (key == 'height') {
            resizeVideo();
        } else if (key == 'position') {
            self.$video.position(value);
        } else if (key == 'width') {
            resizeVideoAndControls();
        }
    }

    that.toggleAnnotations = function() {
        that.$element.toggle(1);
        //that.toggleAnnotations(null, !self.options.showAnnotations);
    };

    that.toggleControls = function() {
        self.$panel.toggle(1);
        //that.toggleControls(null, !self.options.showControls);
    };

    that.toggleMute = function() {
        self.$button.mute.trigger('click');
    };

    that.togglePlay = function() {
        self.$button.play.trigger('click');
    };

    that.toggleSize = function() {
        self.$button.size.trigger('click');
    }

    return that;

}
