if (!window.console) console = {};
console.log = console.log || function(){};
console.warn = console.warn || function(){};
console.error = console.error || function(){};
console.info = console.info || function(){};


function init() {
    initContact();
    initWorks();
    initContents();
}
$(document).observe('dom:loaded', init);


function initContact() {
    if(!$(document.body).hasClassName('contact'))
        return;
    
    // e-address. Wonder if this paranoia is actually worth it.
    var meName = R('cnhy');
    var meDomain = R('tvnaanebf.bet');
    $('my-email').innerHTML = meName + '<span>@</span>' + meDomain;
    $('my-email').href = R('znvygb:') + meName + '@' + meDomain;

    // public key description
    var d = $('public-key-explanation');
    d.hide();
    var d2 = new Element('div').insert(
            new Element('a', {'href': '#'}).addClassName('note').observe('click', function(e) {
                e.stop();
                d.toggle();
            }).update("(What\u2019s this?)"));
    d.parentNode.insertBefore(d2, d)
    $('public-key-explanation').hide();
}



function initWorks() {
}


function ContentsItem(heading, name, children) {
    this.heading = heading;
    this.name = name;
    this.children = children || [];
}

function initContents() {
    $$('div.prose').each(function(p) {
        var toc = [];
        var children = p.childElements();
        for(var i = 0; i < children.length; ++i) {
            var c = children[i];
            var tn = c.tagName.toString().toLowerCase();
            var l = null;
            if(tn == 'h3')
                l = toc;
            else if(tn == 'h4')
                l = toc[toc.length - 1].children;
            else
                continue;

            var name = null;
            var heading = c.firstChild.nodeValue;

            //if(c.firstChild.nodeType == 1) {
                //if(c.tagName.toString().toLowerCase() == 'a') {
                    //name = c.name;
                //}
                //var anchor = c.firstChild;
                //log(anchor);
                //heading = anchor.firstChild.nodeValue;
            //}
            //else {
                //foobar = c.firstChild.nodeValue;
            //}

            if(!name) {
                name = heading.toLowerCase().replace(/ /g, '-').replace(/[^a-zA-Z0-9\-]/g, '');
                c.update(new Element('a', {name: name}).update(heading));
            }
            l.push(new ContentsItem(heading, name));
        }

        var type = 'ul';
        var list = new Element(type);
        var tocEl = new Element('div').addClassName('toc');
        tocEl.appendChild(new Element('div').update('Contents'));
        tocEl.appendChild(list)
        function buildTocElement(container, items) {
            for(var i = 0; i < items.length; ++i) {
                var li = new Element('li').insert(
                    new Element('a', {'href': '#' + items[i].name}).update(items[i].heading));
                container.appendChild(li);
                if(items[i].children) {
                    var newContainer = new Element(type);
                    li.appendChild(newContainer)
                    buildTocElement(newContainer, items[i].children);
                }
            }
        }
        buildTocElement(list, toc);
        p.insert({top: tocEl});
    });
}



/////////////////////// Accordion /////////////////////////////
// Feel free to use this code if you like it, I place it in  //
// the public domain. /////////////////////////////////////////

var Accordion = Class.create({
    initialize: function(togglers, stretchers, options) {
        this.togglers = togglers;
        this.stretchers = stretchers;
        this.hashes = $A(options.hashes || []);
        this.initial = options.initial || null;
        
        this.activeClassName = 'active';
        this.animating = false;
        this.transition = Effect.Transitions.sinoidal;
        
        this.activeStretcher = null;
        this.activeToggler = null;
        
        var toggle = this.toggle;
        // Set up the click handler for the togglers and initialise the
        // stretchers.
        for(var i = 0; i < this.togglers.length; ++i) {
            var t = this.togglers[i];
            t.observe('click', this.togglerClicked.bindAsEventListener(this, t));
            t.observe('mousedown', this.togglerMouseDown.bindAsEventListener(this, t));
            var s = this.stretchers[i];
            var dimensions = s.getDimensions();
            // Keeping track of the original size and telling scriptaculous
            // means that the animation will not jitter at the end when
            // expanding.
            s.originalSize = {
                originalHeight: dimensions.height,
                originalWidth: dimensions.width
            };
            // Stretchers are initially hidden
            s.setStyle({display: 'none'});
        }
        
        var hash = window.location.hash.substr(1);
        if(this.hashes.indexOf(hash) != -1)
            this.initial = this.stretchers[this.hashes.indexOf(hash)];
        if(this.initial) {
            // stop the hash from being set for the initial page
            var h = this.hashes;
            this.hashes = $A([]);
            this.toggle(this.initial, false);
            this.hashes = h;
        }
    },
    
    
    togglerClicked: function(e, toggler) {
        this.toggle(toggler)
    },
    
    togglerMouseDown: function(e, toggler) {
        e.stop();
    },
    
    toggle: function(element, animate) {
        if(typeof animate == 'undefined')
            animate = true;
        
        var stretcher, toggler, index;
        if(this.togglers.indexOf(element) == -1) {
            stretcher = element;
            index = this.stretchers.indexOf(stretcher);
            toggler = this.togglers[index];
        }
        else {
            toggler = element;
            index = this.togglers.indexOf(toggler);
            stretcher = this.stretchers[index];
        }
        
        if(this.animating)
            return;
        if(animate)
            this.animating = true;
        
        if(stretcher == this.activeStretcher) {
            stretcher = toggler = null;
        }
        
        if(stretcher) {
            toggler.addClassName(this.activeClassName);
            stretcher.addClassName(this.activeClassName);
        }
        if(this.activeStretcher) {
            this.activeToggler.removeClassName(this.activeClassName);
            this.activeStretcher.removeClassName(this.activeClassName);
        }
        
        if(animate) {
            var effects = [];
            if(stretcher) {
                effects.push(new Effect.BlindDown(stretcher, {sync: true, transition: this.transition, scaleContent: false, scaleMode: stretcher.originalSize}));
            }
            if(this.activeStretcher) {
                effects.push(new Effect.BlindUp(this.activeStretcher, {sync: true, transition: this.transition, scaleContent: false, scaleMode: this.activeStretcher.originalSize}));
            }
            new Effect.Parallel(effects, {
                duration: 0.6,
                fps: 40,
                afterFinish: function() { this.animating = false; }.bind(this)
            });
        }
        else {
            if(this.activeStretcher)
                this.activeStretcher.hide();
            stretcher.show();
        }
        
        this.activeStretcher = stretcher;
        this.activeToggler = toggler;
        
        if(this.hashes.length > index) {
            var l = stretcher ? this.hashes[index] : '';
            window.location.hash = '#' + l;
        }
    }
});



/////////////////////////// Darkview /////////////////////////////////
///  A little like Fancybox and Lightview for slideshows but free! ///
///                  Also in the public domain.                    ///
//////////////////////////////////////////////////////////////////////

var Darkview = Class.create({
    initialize: function(imgs) {
        this.shadowSize = 17;
        this.effect = null;
        this.screen = new Element('div').hide().setStyle({
            backgroundColor: '#000',
            position: 'fixed', left: 0, top: 0,
            width: '100%', height: '100%'
        }).observe('click', this.close.bind(this));
        document.observe('keydown', this.keyHandler.bindAsEventListener(this));
        this.boxes = [this.createBox()];
        this.boxes.push(this.boxes[0].clone(true));
        this.currentBoxNumber = 0;

        this.panel = new Element('table').addClassName('darkview-control').insert(new Element('tbody'));
       
        var panelItems = [
            ['number', null],
            ['previous', this.showPrevious],
            ['next', this.showNext],
            ['close', this.close]
        ];
        var tr = new Element('tr');
        this.panel.firstChild.appendChild(tr)
        for(var i = 0; i < panelItems.length; ++i) {
            var td = new Element('td').addClassName(panelItems[i][0]);
            if(panelItems[i][1]) {
                td.observe('click', panelItems[i][1].bindAsEventListener(this));
            }
            tr.appendChild(td);
            this[panelItems[i][0] + 'Cell'] = td;
        }
        this.previousCell.addClassName('disabled');
        if(imgs.length == 1)
            this.nextCell.addClassName('disabled');
        
        document.body.appendChild(this.screen);
        document.body.appendChild(this.boxes[0]);
        document.body.appendChild(this.boxes[1]);
        
        //this.imageContainer = $(this.currentBox().firstChild.childNodes[1].childNodes[1]);
        
        this.currentImage = 0;
        this.images = imgs;
        
        this.showScreen(function() {
            this.setImage(imgs[0]);
            document.body.appendChild(this.panel);
            this.updateNumberLabel();
        }.bind(this));
    },

    createBox: function() {
        var b = new Element('table').setStyle({
            position: 'fixed', left: '50%', top: '50%',
            marginLeft: -(5 + this.shadowSize) + 'px',
            marginTop: -(5 + this.shadowSize) + 'px'
        }).addClassName('darkview').insert(new Element('tbody')).hide();
        var tbody = b.firstChild;
        var classNames = [['nw', 'n', 'ne'], ['w', 'c', 'e'], ['sw', 's', 'se']];
        for(var i = 0; i < 3; ++i) {
            var tr = new Element('tr');
            for(var j = 0; j < 3; ++j) {
                tr.appendChild(new Element('td').addClassName(classNames[i][j]));
            }
            tbody.appendChild(tr);
        }
        b.hide();
        return b;
    },

    currentBox: function() { return this.boxes[this.currentBoxNumber] },
    otherBox: function() { return this.boxes[Math.abs(this.currentBoxNumber - 1) % 2] },
    imageContainer: function(box) {
        return $((box || this.currentBox()).firstChild.childNodes[1].childNodes[1]);
    },

    
    showScreen: function(afterFinish) {
        this.screen.appear({duration: 0.3, from: 0, to: 0.6, afterFinish: function() {
            this.currentBox().show();
            if(afterFinish)
                afterFinish();
        }.bind(this)});
    },
    
    setImage: function(img, direction) {
        direction = direction || 1;
        if(typeof img == 'string') {
            var src = img;
            img = new Image();
            img.src = src;
        }
        img = $(img);
        if(!img.complete) {
            // if it hasn't loaded, wait.
            setTimeout(this.setImage.bind(this, img, direction), 500);
            return;
        }
        var currentContainer = this.imageContainer(this.currentBox());
        var otherContainer = this.imageContainer(this.otherBox());
        //alert(this.imageContainer(this.otherBox()));

        currentContainer.setStyle(
                {width: img.width + 'px', height: img.height + 'px'});

        if(this.effect)
            this.effect.cancel();

        var w = document.viewport.getWidth();

        var center = -parseInt(img.width / 2 + this.shadowSize);
        var right = parseInt(w / 2);
        var left = 0;
            if(otherContainer.childNodes.length) {
                left = -parseInt(w / 2) - otherContainer.firstChild.width - this.shadowSize - this.shadowSize;
            }

        if(direction == -1) {
            var x = right;
            right = left;
            left = x;
        }

        this.currentBox().setStyle({
            marginTop: -parseInt(img.height / 2 - this.shadowSize) + 'px'
        });
        if(direction == 1) {
            this.currentBox().setStyle({marginLeft: right + 'px'});
        }
        else {
            this.currentBox().setStyle({marginLeft: -parseInt(w / 2) - img.width - this.shadowSize + 'px'});
        }

        currentContainer.update();
        currentContainer.appendChild(img);
        this.currentBox().show();
        var currentStyle = {marginLeft: center + 'px'};
        var otherStyle = {marginLeft: left + 'px'};
        this.effect = new Effect.Parallel([
            new Effect.Morph(this.currentBox(), {style: currentStyle, sync: true}),
            new Effect.Morph(this.otherBox(), {style: otherStyle, sync: true})
        ], {duration: 0.4});

        this.currentBoxNumber = (this.currentBoxNumber + 1) % 2;
    },
    
    hideScreen: function(afterFinish) {
        this.screen.fade({duration: 0.3, from: 0.6, to: 0, afterFinish: afterFinish});
    },

    keyHandler: function(e) {
        switch(e.keyCode) {
            case 37: this.showPrevious(); break;
            case 39: this.showNext(); break;
            case 27: this.close(); break;
        }
    },
    
    showPrevious: function() {
        if(this.currentImage == 0)
            return;
        this.nextCell.removeClassName('disabled');
        this.setImage(this.images[--this.currentImage], -1);
        if(this.currentImage == 0)
            this.previousCell.addClassName('disabled');
        this.updateNumberLabel();
    },
    
    showNext: function() {
        if(this.currentImage == (this.images.length - 1))
            return;
        this.previousCell.removeClassName('disabled');
        this.setImage(this.images[++this.currentImage], 1);
        if(this.currentImage == (this.images.length - 1))
            this.nextCell.addClassName('disabled');
        this.updateNumberLabel();
    },
    
    updateNumberLabel: function() {
        var s = (this.currentImage + 1) + ' / ' + this.images.length;
        this.numberCell.update(s);
    },
    
    close: function() {
        document.body.removeChild(this.boxes[0]);
        document.body.removeChild(this.boxes[1]);
        this.panel.remove();
        this.hideScreen(function() {
            this.screen.remove();
        }.bind(this));
        document.stopObserving('keypress');
    }
});




/////////////////////// ROT13

function rot( t, u, v ) {  return String.fromCharCode( ( ( t - u + v ) % ( v * 2 ) ) + u ); }
function R( s ) {  var b = [], c, i = s.length,   a = 'a'.charCodeAt(), z = a + 26,   A = 'A'.charCodeAt(), Z = A + 26;  while(i--) {   c = s.charCodeAt( i );   if( c>=a && c<z ) { b[i] = rot( c, a, 13 ); }   else if( c>=A && c<Z ) { b[i] = rot( c, A, 13 ); }   else { b[i] = s.charAt( i ); }  }  return b.join( '' ); } 
function rot5( s ) {  var b = [], c, i = s.length,   a = '0'.charCodeAt(), z = a + 10;  while(i--) {   c = s.charCodeAt( i );   if( c>=a && c<z ) { b[i] = rot( c, a, 5 ); }   else { b[i] = s.charAt( i ); }  }  return b.join( '' ); } 
function rot135( s ) {  return R( rot5( s ) ); }

