//# sourceURL=widgets/Camera.js
/**
 * $Id: Camera.js 302 2018-03-16 21:11:51Z patrick $
 */
/* globals SlapDash */

/* TO-DO:

1) DONE: Camera controls (for touch/tablets) -- forward, back, pause, play
2) Overlay camera name options

*/

import Widget from '../Widget.js';

var Camera = function( elem ) {
    Widget.call(this, elem);
    this.name = "Camera";

    this.delay = this.getData( "delay", 5 );
    this.backgrounddelay = this.getData( "background-delay", 60 );
    this.updatePending = 0;
    this.needsResize = true;
    this.hovering = false;
    this.paused = false;
    this.timeoutHandle = false;
    this.pagevisible = true;

    const self = this;
    this.sources = [];
    this.sourceEntities = {};
    if ( undefined !== this.entity_id ) {
        this.sources.unshift( this.entity_id );
    }
    const list = $( 'li', elem );
    if ( list.length > 0 ) {
        $("li", elem).each( function( /* ix */ ) {
            self.sources[self.sources.length] = $(this).text().trim();
        });
    }
    this.lastSource = 0;
    // this.source = this.sources[0];

    $(elem).addClass("widget-camera");
};

Camera.prototype = Object.create(Widget.prototype);
Camera.prototype.constructor = Camera;

Camera.prototype._tick = function() {
    this.log.debug(6, "tick!");
    const self = this;
    self.timeoutHandle = false;
    self.update( self, self );
    /* Schedule next tick, short if page visible, long otherwise */
    const d = self.pagevisible ? self.delay : self.backgrounddelay;
    this.timeoutHandle = window.setTimeout( function() { self._tick(); }, d * 1000 );
};

Camera.prototype.start = function() {
    Widget.prototype.start.call( this );

    for (let ix=0; ix<this.sources.length; ++ix) {
        this.sourceEntities[ this.sources[ix] ] = SlapDash.findEntity( this.sources[ix] );
    }

    // Hook PageVisibility
    const self = this;
    self.pagevisible = true;
    if ( $.support.pageVisibility ) {
        $(document).on({ 'show.visibility': function() {
                self.pagevisible = true;
                self.log.debug(5, "show.visibility handler: page is now visible");
                if ( self.timeoutHandle ) {
                    window.clearTimeout( self.timeoutHandle );
                    self.timeoutHandle = false;
                }
                self._tick();
            },
            'hide.visibility': function() {
                self.pagevisible = false;
                self.log.debug(5, "show.visibility handler: page is now hidden");
            }
        });
    } else {
        self.log.debug(5, "Page Visibility is not natively supported by this browser");
    }

    this._tick(); /* Launch our first tick */
};

Camera.prototype.stop = function() {
    if ( this.timeoutHandle ) {
        clearTimeout( this.timeoutHandle );
    }
};

Camera.prototype.layoutInit = function( layoutName, descObj ) {
    /* onLoad handler: when the image finishes loading, copy it to the background,
       which is where the actual display happens, and scale it to fit. */
    const self = this;
    $('img', self.elem).on('load', function( ev ) {
        $(self.elem).css( 'background-image', 'url(' + $(ev.currentTarget).attr('src') + ')' );
        self.resized();
    });

    $('div.control#pause', this.elem).click( function( e ) {
        self.paused = ! self.paused;
        self.log.debug( 5, 'pause=' + self.paused);
        if ( self.paused ) {
            $(this).removeClass('entypo-pause').addClass('entypo-play');
        } else {
            $(this).removeClass('entypo-play').addClass('entypo-pause');
        }
        e.preventDefault(); e.stopPropagation();
        return false;
    });

    $('div.control#back', this.elem).click( function( e ) {
        self.paused = true;
        $('div.control#pause', $(this).parent()).removeClass('entypo-pause').addClass('entypo-play');
        if (--self.lastSource < 0) self.lastSource = self.sources.length - 1;
        e.preventDefault(); e.stopPropagation();
        clearTimeout( self.timeoutHandle );
        self.timeoutHandle = false;
        self.update();
        self.timeoutHandle = window.setTimeout( function() { self._tick(); }, self.delay );
        return false;
    });

    $('div.control#fwd', this.elem).click( function( e ) {
        self.paused = true;
        $('div.control#pause', $(this).parent()).removeClass('entypo-pause').addClass('entypo-play');
        if (++self.lastSource >= self.sources.length) self.lastSource = 0;
        e.preventDefault(); e.stopPropagation();
        clearTimeout( self.timeoutHandle );
        self.timeoutHandle = false;
        self.update();
        self.timeoutHandle = setTimeout( function() { self._tick(); }, self.delay );
        return false;
    });

    $(this.elem).mouseenter( function() {
        if ( !self.paused ) {
            if (!self.hovering) {
                $(".overlay", self.elem).append("<span id='hov'> HOVERING/PAUSED</span>");
            }
            self.hovering = true;
        }
    });
    $(this.elem).mouseleave( function() {
        if ( !self.paused ) {
            $(".overlay #hov", self.elem).remove();
            self.hovering = false;
        }
    });

    // Only show controls if multiple cameras
    if ( this.sources.length <= 1 ) {
        $('div.controls', this.elem).hide();
    } else {
        $('div.controls', this.elem).show();
    }
};

Camera.prototype.update = function( ) {
    // If another process is fetching an image (long-running?) skip this
    if (this.updatePending++) return;

    if ( ! ( this.hovering || this.paused ) ) {
        this.lastSource += 1;
        if ( this.lastSource >= this.sources.length ) {
            this.lastSource = 0;
        }
    }

    // Load the image
    let fullurl = false;
    const cid = this.sources[ this.lastSource ];
    if ( cid ) {
        if ( ! this.sourceEntities[ cid ] ) {
            this.sourceEntities[ cid ] = SlapDash.findEntity( cid );
        }
        if ( this.sourceEntities[ cid ] ) {
            fullurl = SlapDash.config.baseurl.replace( /\/[^/]+\/?$/, "") + "/api/camera/" +
                this.sourceEntities[cid].getID() + "/snapshot?r=" + Date.now();
        }
    }
    if ( !fullurl ) {
        fullurl = SlapDash.config.baseurl + "/images/nocamera.png";
    }
    this.log.debug(6, "%1 setting image src to %2", this, fullurl);
    $('img', this.elem).attr("src", fullurl); /* onLoad will copy image (src) to background */

    const ovl = cid + ( this.paused ? " CYCLING PAUSED (PRESS PLAY TO RESUME)" : "" );
    $('.overlay', this.elem).text( ovl );
    if (this.hovering && this.sourceEntities.length > 1) $('.overlay', this.elem).append("<span id='hov'> HOVERING/PAUSED</span>");

    $(this.elem).removeClass("active nodata update-pending");
    this.updatePending = 0; /* Release "lock" last */
};

Camera.prototype.click = function() {
    this.update( this, this );
};

/* Called when gridster finishes resizing a widget */
Camera.prototype.resized = function() {
    // Scale the image to preserve the original aspect ratio
    const nativeX = $('img', this.elem).get(0).width;
    const nativeY = $('img', this.elem).get(0).height;
    if (nativeX <= 0 || nativeY <= 0) return;
    const widgetX = $(this.elem).get(0).scrollWidth;
    const widgetY = $(this.elem).get(0).scrollHeight;
    let asp = widgetX / nativeX;
    let newX = Math.floor(nativeX * asp);
    let newY = Math.floor(nativeY * asp);
    if (newY > widgetY) {
        asp = widgetY / nativeY;
        newX = Math.floor(nativeX * asp);
        newY = Math.floor(nativeY * asp);
    }
    // self.log.debug( 5, 'new size is ' + newX + "x" + newY);
    $(this.elem).get(0).style.backgroundRepeat = "no-repeat";
    $(this.elem).get(0).style.backgroundPosition = "center center";
    $(this.elem).get(0).style.backgroundSize = newX + "px " + newY + "px";
    this.needsResize = false;
};

export default Camera;
