﻿var G = {
    set: function (a, b) {
        for (var o in b){
            a[o] = b[o];
        }
        return a;
    },
    create: function (a, b, c, d) {
        var o = (d || document).createElement(a);
        G.set(o, b);
        G.set(o.style, c);
        return o;
    },
    append: function (a, b, c, d) {
        var o = b.tagName ? b : G.create(b, c, d);
        a.appendChild(o);
        return o;
    }
}

function Clock(clockId,interval,startTimeMillisec){
    this.startTime = new Date(startTimeMillisec);
    this.beginTime = new Date();
    this.tickInterval = interval;
    this.clock = document.getElementById(clockId);
    this.init = function(){
        var o = this.clock;
        if (o){
           this.prepare(o);
        }
    };
    this.prepare = function (a) {
        var r = this.radius = a.offsetWidth / 2;
        this.isCanvasSupported(this);
        if (this.html5)
        {
            var c = G.create('canvas', {className: 'clockCanvas', id:'canvas'+clockId});
            G.append(a, c);
            this.ctx = document.getElementById('canvas'+clockId).getContext('2d');
            this.ctx.canvas.width=a.offsetWidth;
            this.ctx.canvas.height=a.offsetWidth;
        } else {
            var o = G.create('div', {className: 'face'});
            this.make('hh', 0.5, o);
            this.make('mm', 0.75, o);
            G.append(a, o);
            this.setHrs(o, r);
        }
        var sender = this;
        this.tick(sender);
        this.timer = setInterval(function(){sender.tick(sender);}, this.tickInterval);
        
    };
    this.isCanvasSupported = function(sender){
        var elem = document.createElement('canvas');
        if ( !!(elem.getContext && elem.getContext('2d')) ){sender.html5 = true;}else{sender.html5 = false;}
        return sender.html5;
    };
    this.make = function (a, b, c) {
        var m = this;
        var n = Math.floor(m.radius * b);
        var o = m[a] = [];
        for (i = 0; i < n; i++){
            o[i] = G.append(c, 'div', {className: a});
        }
    };
    this.setHrs = function (o, r) {
        var p;
        var M = Math;
        var P = M.PI;
        var rp;
        var n = r * 0.9;
        for (i = 0; i < 12; i++) {
            p = o.childNodes[i];
            rp = (i + 1) * 2 * P / 12 - P / 2;
            G.set(p.style, {
                top: r + M.sin(rp) * n - p.offsetHeight / 2 + 'px',
                left: r + M.cos(rp) * n - p.offsetWidth / 2 + 'px'
            });
        }
    };
    this.tick = function (sender) {
        var m = sender;
        var d = new Date(sender.startTime.getTime()+ (new Date() - sender.beginTime));
        var hh;
        var mm;
        var ss;
        var f = m.update;
        try {
            ss = d.getSeconds() + d.getMilliseconds() / 1000;
            mm = d.getMinutes() + ss / 60;
            hh = d.getHours() + mm / 60;
            if ( sender.html5 ) {
                this.updateHtml5(m,d.getHours(), d.getMinutes(), d.getSeconds());
            } else {
                f(m,m.hh, hh % 12, 12);
                f(m,m.mm, mm, 60);
            }
        } catch (e) {
            m.stop(sender);
        }
        
    };
    this.updateHtml5 = function(s, hr, min, sec) {
        var r = s.radius;
        var c = s.ctx;
                
        c.save();  
        c.clearRect(0,0,r*2,r*2);  
        c.translate(r,r);  
        c.scale(0.4,0.4);  
        c.rotate(-Math.PI/2);  
        c.strokeStyle = "black";  
        c.fillStyle = "white";  
        c.lineWidth = 8;  
        c.lineCap = "round";  

        hr = hr>=12 ? hr-12 : hr;  

        c.fillStyle = "black";  

        // write Hours  
        c.save();  
        c.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec )  
        c.lineWidth = 4;  
        c.beginPath();  
        c.moveTo(0,0);  
        c.lineTo(40,0);  
        c.stroke();  
        c.restore();  

        // write Minutes  
        c.save();  
        c.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec )  
        c.lineWidth = 2;  
        c.beginPath();  
        c.moveTo(0,0);  
        c.lineTo(66,0);  
        c.stroke();  
        c.restore();  
        c.restore();  
    };  
    this.degreesToRadians = function(degrees){
        return degrees * (Math.PI / 180);
    };
    this.update= function (sender,a, b, c) {
        var M = Math;
        var P = M.PI;
        var rp = b * P * 2 / c - P / 2;
        var r = sender.radius;
        for (i = 0; i < a.length; i++){        
            G.set(a[i].style, {
                top: r + M.sin(rp) * i + 'px',
                left: r + M.cos(rp) * i + 'px'
            });
        }
    };
    this.stop = function (sender) {
        clearInterval(sender.timer);
    };
};

