// Copyright (c) 2009, Braydon Fuller

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  
// 02110-1301, USA.

function Video(params){
    this.nativeVideo = false
    this.element = false
    this.video = false
    this.controller = false
    this.widths = [480, 640]

    function bool(b) { if (b) return 1; return 0;}
    function hq(s) { return '"' + hx( s ) + '"';}
    function hx(s){
        if ( typeof s != 'String' ) { s = s.toString() }
        return s.replace( /&/g, '&amp;' )
            . replace( /</g, '&lt;' )
            . replace( />/g, '&gt;' );
    }
    function hasattr(elem,attr) {
	var isset;
	try {
	    eval("isset=typeof elem."+attr+"!='undefined';");
	} catch (e) {
	    isset=false;
	}
	return isset;
    }
    function dir(ob){
	var a=[],attr
	for(attr in ob){a.push(attr)}
	return a.sort().join(' ')
    }
    // Detect <video> element, and supported API
    this.detect = function() {
	// 'object' for Firefox & Safari, and 'function' for Opera
	if ( typeof HTMLVideoElement == 'object' || 
	     typeof HTMLVideoElement == 'function'){
	    hve = document.createElement('video');
	    // check to see if we have the needed API, at some
	    // point this should support a wider range
	    if(hasattr(hve, 'currentTime') && hasattr(hve, 'play') && 
	       hasattr(hve, 'pause') && hasattr(hve, 'duration') && 
	       hasattr(hve, 'volume')) {
		this.nativeVideo = true;
	    }

	}
        /* Safari 3.1.2 can play the video (mov, mp4), and has all the 
           right API, but I could not get it to stream the video correctly.
           perhaps we will wait until Safari 4. Opera can play OGG video
           but is lacking the right API. So we will let Safari use Flash
           for the time being.
        */
//         var useragent = navigator.userAgent.toLowerCase();
//         var isSafari = useragent.match(/version\/([\d\.]*) safari/);
//         if (isSafari) {
//             this.nativeVideo = false;
//         }
    }
    this.attributionTag = function(params){
        return '<p class="universvideo" style="margin-top:5px;width:'+params.embed_size[0] +'px;font-family:'+params.display.font_family+';font-size:'+params.display.font_size+'px;"><a href="'+params.display.video_url+'">'+params.display.video_title+' (View Larger) </a></p>';
    }
    this.attributionTagFlash = function(params){
        return '<p class="universvideo" style="margin-top:5px;width:'+params.embed_size[0] +'px;font-family:'+params.display.font_family+';font-size:'+params.display.font_size+'px;"><a href="'+params.display.video_url+'">'+params.display.video_title+' (View Larger) </a></p>';
    }
    // Insert <video> element
    this.embedVideoElement = function(elm, params) {
        var poster = params.base_url + params.size[0] + "/" + params.base_file + ".jpg"
        var eid = params.id + "_embed"
	var vid = params.id + "_v"
	var cid = params.id + "_vc"
	var pid = params.id + "_p"
	var form_name = params.id + "_form"
        var ebid = params.id + "_embedbutton"
	var poster_html = '<img id=' + hq(pid) + 'src=' + hq(poster) + ' style="position:absolute;top:0;left:0;z-index:2">'
        var object_embed = '<object type="text/html" data="' + params.display.object_url + '" style="width:' + params.embed_size[0] + 'px;height:' + params.embed_size[1] + 'px;overflow:hidden;"></object>' + this.attributionTag(params);
        object_embed = object_embed.replace(/"/g,'&#34;')
        object_embed = object_embed.replace(/</g,'&lt;')
        object_embed = object_embed.replace(/>/g,'&gt;')
        var flash_embed = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" width="' + params.embed_size[0] + '" height="' + params.embed_size[1] + '"><param name=movie value="' + params.flash + '"><param name=quality value="high"><param name="wmode" value="transparent"><param name=FlashVars value="autoplay=false&width=' + params.embed_size[0] + '&height=' + params.embed_size[1] + '&embed_width=' + params.embed_size[0] + '&embed_height=' + params.embed_size[1] + '&base_url=' + params.base_url + '&base_file=' + params.base_file + '&video_title=' + params.display.video_title + '&video_url=' + params.display.video_url + '&site_title=' + params.display.site_title + '&site_url=' + params.display.site_url + '&bgcolor=' + params.bgcolor + '&object_url=' + params.display.object_url + '&font_size=' + params.display.font_size + '&font_family=' + params.display.font_family + '&flash_url=' + params.flash + '"><param name=bgcolor value="' + params.bgcolor + '"><embed src="' + params.flash + '" FlashVars="autoplay=false&width=' + params.embed_size[0] + '&height=' + params.embed_size[1] + '&embed_width=' + params.embed_size[0] + '&embed_height='+ params.embed_size[1] +'&base_url=' + params.base_url + '&base_file=' + params.base_file + '&video_title=' + params.display.video_title + '&video_url=' + params.display.video_url + '&site_title=' + params.display.site_title + '&site_url=' + params.display.site_url + '&bgcolor=' + params.bgcolor + '&object_url=' + params.display.object_url + '&font_size=' + params.display.font_size + '&font_family=' + params.display.font_family + '&flash_url=' + params.flash + '" quality="high" bgcolor="' + params.bgcolor + '" width="' + params.embed_size[0] + '" height="'+ params.embed_size[1] +'" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" wmode="transparent"></embed></object>' + this.attributionTagFlash(params);
        flash_embed = flash_embed.replace(/"/g,'&#34;')
        flash_embed = flash_embed.replace(/</g,'&lt;')
        flash_embed = flash_embed.replace(/>/g,'&gt;')
        var input_style = 'style="border:1px solid #eee; margin-top:1%; background-color:#eee;font-color:#000;font-size:' + ( params.display.font_size * 1.3 ) + 'px;'
	var html = '<div style="position:relative;background-color:#'+params.bgcolor+'">' + poster_html + '<canvas id=' + hq( cid ) +
	    ' width=' + hq( params.size[0] ) +
	    ' height="28" style="position:absolute;top:'+ (params.size[1] - 28) +
	    'px;left:0;z-index:3;"></canvas>' +
            '<div id="' + eid + '" style="display:none;font-family:' + params.display.font_family + ';font-size:'+params.display.font_size+'px;position:absolute;background-color:#999;color:#fff;text-align:center;top:0;left:0;z-index:4;width:' + params.size[0] + 'px;height:'+(params.size[1]-28)+'px;opacity:0.9;">' + 
            '<form name="' + form_name + '">' +
            '<div style="margin-top:5%;" onclick="document.' + form_name + '.allcode.focus();document.' + form_name + '.allcode.select();"><strong>HTML 5 Video or Flash</strong> <em>(for your domain)</em><br><input name="allcode" type="text" ' + input_style + 'width:50%;" value="' + object_embed + '"></input></div>' +
            '<div style="margin-top:5%;" onclick="document.' + form_name + '.flashcode.focus();document.' + form_name + '.flashcode.select();"><strong>Flash</strong> <em>(for social networks)</em><br><input name="flashcode" type="text" ' + input_style + 'width:70%;" value="' + flash_embed + '"></input></div>' +
            '<div style="margin-top:5%;" onclick="document.' + form_name + '.urlcode.focus();document.' + form_name + '.urlcode.select();"><strong>URL</strong> <em>(for email, microblogs, and chat)</em><br><input name="urlcode" type="text" ' + input_style + 'width:30%;" value="' + params.display.video_url + '"></input></div>' +
            '</form>' +
            '</div>' +
            '</div>';
	elm.innerHTML = html
        if(params.display.show){
            pelm = elm.parentNode
            attr = document.createElement('div')
            attr.innerHTML = this.attributionTag(params)
            pelm.appendChild(attr)
        }
    }
    // Embed Native or Flash Video
    this.init = function(params) {
	this.detect()
	this.element = document.getElementById(params.id)
	if (this.nativeVideo){
            this.embedVideoElement(this.element, params)
	    this.video = document.getElementById(params.id+"_v")
	    this.controller = new VideoController(params)
	} 
	this.element.style.width = params.size[0]+"px"
	this.element.width = params.size[0]
    }
    if (params){
	this.init(params)
    }
    if (params.autoplay) {
 	poster = document.getElementById(params.id + "_p");
 	video = document.getElementById(params.id + "_v");
        if (poster){
            poster.style.display = "none"
        }
        if(video){
            video.pause()
            video.play()
        }
    }
};

function VideoController(params){
    var duration = 100, time = 1, progress = 1, muted = false, scrub = null,
    tbx = null, tbw = null, cint = null, params = params, video = null,
    element = null, wrapper = null, poster = null, playing = true;

    var drawhbar = function(ctx,w,h,xs,ys,rgba){
	var bxd = w          //bar x distance
	var bxs = xs         //bar x start
	var bxe = bxs+bxd    //bar x end
	var bys = ys         //bar y start
	var bye = ys+h       //bar y end
	ctx.fillStyle = rgba
	ctx.beginPath()
	ctx.moveTo(bxs+4, bys)
	ctx.lineTo(bxe-4, bys)
	ctx.bezierCurveTo(bxe-4, bys, bxe, bys, bxe, bys+4)
	ctx.bezierCurveTo(bxe, bys+4, bxe, bye, bxe-4, bye)
	ctx.lineTo(bxs+4, bye)
	ctx.bezierCurveTo(bxs+4, bye, bxs, bye, bxs, bys+4)
	ctx.bezierCurveTo(bxs, bys+4, bxs, bys, bxs+4, bys)
	ctx.closePath()
	ctx.fill()
    }
    var drawvbar = function(ctx,w,h,x,y,c){
	ctx.fillStyle = c
	ctx.beginPath()
	var r=w/2,xr=x+r,xw=x+w,yh=y+h,yhr=yh-r,yr=y+r
	ctx.beginPath()
	ctx.moveTo(xr,y);ctx.bezierCurveTo(xr,y,xw,y,xw,yr);ctx.lineTo(xw,yhr)
	ctx.bezierCurveTo(xw,yhr,xw,yh,xr,yh);ctx.bezierCurveTo(xr,yh,x,yh,x,yhr)
	ctx.lineTo(x,yr);ctx.bezierCurveTo(x,yr,x,y,xr,y)
	ctx.closePath()
	ctx.fill()
   }
   var drawplay = function(ctx,on,x,y,c){
	ctx.save()
	ctx.translate(x,y)
	ctx.fillStyle=c;
	switch (on) {
	case true:
	    ctx.beginPath();ctx.moveTo(0,0);ctx.lineTo(0,12);
	    ctx.lineTo(4,12);ctx.lineTo(4,0);ctx.closePath();ctx.fill()
	    ctx.beginPath();ctx.moveTo(7,0);ctx.lineTo(7,12);
	    ctx.lineTo(11,12);ctx.lineTo(11,0);ctx.closePath();ctx.fill()
	    break;
	case false:
	    ctx.beginPath()
	    ctx.moveTo(0,0);ctx.lineTo(9,6);ctx.lineTo(0,12);
	    ctx.closePath();ctx.fill();
	    break;
	}
	ctx.restore()
    }
    var drawvolume = function(ctx,m,x,y,c){
        ctx.save()
	ctx.fillStyle = c
	var yf=y+4,yt=y+11,xe=x+8,xt=x+3
	ctx.beginPath()
	ctx.moveTo(x, yf);ctx.lineTo(x, yt);ctx.lineTo(xt, yt)
	ctx.lineTo(xe, y+15);ctx.lineTo(xe, y);ctx.lineTo(xt, yf)
	ctx.closePath(); ctx.fill()
	if (!m) {
	    ctx.beginPath(); ctx.strokeStyle = c; ctx.lineWidth = 2
	    x=x+10,y=y+4; ctx.moveTo(x,y)
	    ctx.bezierCurveTo(x,y,x+5,y+2.7,x,y+7)
	    ctx.stroke()
            ctx.closePath()
	}
        ctx.restore()
    }
    var embedimg = new Image()
    embedimg.src = params.base_url + 'share.png'
    var drawembed = function(ctx,x,y,c){
        ctx.save()
        //ctx.font = "bold 13px Arial"
        //ctx.fillStyle = c
        //ctx.fillText("SHARE", x+24, y+9)
        ctx.drawImage(embedimg, x+24, y-1)
        ctx.strokeStyle = c
        ctx.lineWidth = 2
        ctx.beginPath()
        ctx.moveTo(x+5,y)
        ctx.lineTo(x, y+4.5)
        ctx.lineTo(x+5,y+9)
        ctx.moveTo(x+12,y-2)
        ctx.lineTo(x+8,y+11)
        ctx.moveTo(x+15, y)
        ctx.lineTo(x+20, y+4.5)
        ctx.lineTo(x+15, y+9)
        ctx.stroke()
        ctx.closePath()
        ctx.restore()
    }
    var drawscrub = function(ctx,x,y){
	drawvbar(ctx,11,20,x-4,y,"rgba(255,255,255,1)")
	drawvbar(ctx,7,16,x-2,y+2,"rgba(70,70,70,1)")
    }
    var drawtime = function (ctx,x,y,w){
//         var log = document.createElement('div')
//         log.innerHTML = '' + progress + ', ' + time + ', ' + progress
//         document.body.appendChild(log)
	drawhbar(ctx,w,8,x,y,"rgba(154,154,154,0.8)")
	drawhbar(ctx,progress/100*w,8,x,y,"rgba(200,200,200,0.8)")
	drawhbar(ctx,time/duration*w,8,x,y,"rgba(255,255,255,1)")
    }

    var draw = function (ctx,w,h){
	ctx.clearRect(0,0,w,h);
	ctx.save();
	ctx.translate(0,h-28)
	ctx.fillStyle = "rgba(20,20,20, 0.7)"
	ctx.fillRect (0,0,w,28)
	tbw = w-140
	tbx = 28
        drawtime(ctx,tbx,10,tbw)
	scrub = (time / duration * tbw) + tbx
        drawscrub(ctx,scrub,4)
	playing = true
	if(video){
            if (video.paused) {
	        playing = false
	    }
        } else {
            playing = false
        }
	drawplay(ctx,playing,10,8,"rgba(255,255,255,1)");
	drawvolume(ctx,muted,w-100,6,"rgba(255,255,255,1)")
	drawembed(ctx,w-75,9.5,"rgba(255,255,255,0.8)")
	ctx.restore();
    }
    var clear = function(ctx,w,h) {
	ctx.clearRect(0,0,w,h);
    }
    var mouseout = function() {
	var c = element
	var ctx = c.getContext("2d")
	var w = c.width, h = c.height
	clear(ctx,w,h)
	clearInterval(cint)
	c.removeEventListener('mousemove', scrubber, false)
    }
    var mousedown = function (ev) {
        t = this.parentNode.parentNode
	var c = element
	var x = ev.layerX - c.offsetLeft
	var y = ev.layerY - c.offsetTop
	var w = c.width
	var h = c.height
	playing = true
	if(video){
            if (video.paused) {
	        playing = false
	    }
        } else {
            playing = false
        }
	if (x <= 28){
	    if(playing){pause();}else{play();}
	} else if (x >= w-110 && x <= w-81){
	    if(muted){unmute();}else{mute();}
	} else if (x >= w-80){
            var embstage = document.getElementById(params.id + "_embed");
            if(embstage.style.display == "none"){
                embstage.style.display="block"
            } else {
                embstage.style.display="none"
            }
	} else if (x >= scrub-4 && x <= scrub+8){
	    c.addEventListener('mousemove', scrubber, false)
	} else {
	    var s = Math.round((x - tbx) / tbw * duration)
	    if (s > duration) s = duration
	    if (s < 0) s = 0
	    seek(s)
	}
	var ctx = c.getContext("2d");
	clear(ctx,w,h);
	draw(ctx,w,h);
    }
    var mouseup = function(ev){
	var c = element
	c.removeEventListener('mousemove', scrubber, false)
    }
    var scrubber = function(ev) {
	var c = element
	var x = ev.layerX - c.offsetLeft;
	var s = Math.round((x - tbx) / tbw * duration)
	if (s > duration) s = duration
	if (s < 0) s = 0
	seek(s)
    }
    var updateprogress = function(ev){
	if (ev.lengthComputable) {
	    if (ev.total != 0){
		progress = notzero(Math.round(ev.loaded/ev.total*100),1)
	    }
	    return;
	}
	if (ev.total) {
            progress = notzero((100*ev.loaded/ev.total).toFixed(0),1)
	}
	return;
    }

    var notzero = function(x,alt){
        if (x == 0 || x == '0'){
            return alt;
        }
        return x;
    }

    var updatetime = function() {
        if(!video)
            return null;
        var v = video
	var n = "" + Math.round(v.currentTime*10)/10;
	if (n.toString() == "NaN") {
	    time = 1;
	} else {
	    time = notzero(n,1);
	}
    }
    var updateduration = function() {
        if(!video)
            return 100;
	var v = video
	var n = Math.round(v.duration*10)/10;
	if (n.toString() == "NaN") {
	    duration = 100;
	  this.duration = 100;
	} else {
	    duration = notzero(n,100);
	    this.duration = notzero(n,100);
	}
    }

    function videotag(params){
        var sources = [[params.base_url + params.size[0] + "/" + params.base_file + ".ogg", "video/ogg"],
                       [params.base_url + params.size[0] + "/" + params.base_file + ".mp4", "video/mp4"]]
	var vid = params.id + "_v"
	var html = ''
	var autoplay_html = ''
	if (params.autoplay) {
	    autoplay_html = ' autoplay="true"'
	}
	html += '<video id=' + hq( vid ) + ' width=' + hq( params.size[0] ) + 
	        ' height=' + hq( params.size[1] ) + autoplay_html + 
                ' style="position:absolute;top:0;left:0;z-index:1;">';

	for(var i=0,l=sources.length;i<l;i++){
	    html += '<source src=' + hq(sources[i][0]) +
		    ' type=' + hq(sources[i][1]) + '/>';
	}
	html += ' </video>';
	return html;
    }

    function initvideo(params) {
        if (params.autoplay){
            playing = true
        } else {
            playing = false
        }
        var newdiv = document.createElement('div')
        newdiv.innerHTML = videotag(params)
	elm = document.getElementById(params.id).firstChild
        elm.appendChild(newdiv)
	var video = document.getElementById(params.id + "_v")
	video.addEventListener('loadedmetadata', updateduration, false)
	video.addEventListener('durationchanged', updateduration, false)
	video.addEventListener('timeupdate', updatetime, false)
	video.addEventListener('progress', updateprogress, false)
        return video
    }
    var play = function(){
        if(!video){
            video = initvideo(params)
        }
        poster.style.display = "none"
	//poster.style.zIndex = 1;
	//video.style.zIndex = 2;
	//video.play()
        video.pause()
        video.play()
    }
    this.play = play
    var stop = function(){var v = video;v.pause();v.currentTime = 0}
    this.stop = stop
    var pause = function(){video.pause()}
    this.pause = pause
    var mute = function(){video.volume = 0;muted = true}
    this.mute = mute
    var seek = function(t){video.currentTime = t;}
    this.seek = seek
    var unmute = function(){video.volume = 1;muted = false}
    this.unmute = unmute
    var drawcontroller = function(ev) {
        updateduration()
        updatetime()
	var c = element
	var ctx = c.getContext("2d")
	var w = c.width, h = c.height
	draw(ctx,w,h)
    }
    var mouseover = function(ev) {
	var c = element
	var ctx = c.getContext("2d")
	var w = c.width, h = c.height
	cint = setInterval(drawcontroller, 20)
    }

    function hq(s) { return '"' + hx( s ) + '"';}
    function hx(s){
    if ( typeof s != 'String' ) { s = s.toString() }
    return s.replace( /&/g, '&amp;' )
      . replace( /</g, '&lt;' )
      . replace( />/g, '&gt;' );
	}

    this.init = function(params) {
        try{
        if (params.autoplay){
            video = initvideo(params)
        }
	element = document.getElementById(params.id + "_vc")
	wrapper = document.getElementById(params.id)
	poster = document.getElementById(params.id + "_p")
	wrapper.addEventListener('mouseover', mouseover, false)
	wrapper.addEventListener('mouseout', mouseout, false)
	element.addEventListener('mousedown', mousedown, false)
	element.addEventListener('mouseup', mouseup, false)
        }catch(e){alert(e)};
    }
    this.init(params)
}

