$( function(){
 
    var v2 = function(v) { return ( (0 <= v && v <= 9) ? "0" : "" ) + v };

    var parseRfc3339;

    Date.prototype.rfc3339 = function( s )
    {
        if( s == undefined ){
            var ofs = this.getTimezoneOffset();
            var z = "+";
            var r;
            if( ofs < 0 ){
                z = "-";
                ofs = -ofs;
            }
            z += v2( Math.floor( ofs / 60 ) ) + ":";
            z += v2( Math.floor( ofs % 60 ) );
            
            r= this.getFullYear() + "-" + 
                v2( this.getMonth() +1 ) + "-" +
                v2( this.getDate() ) + 
                "T" + v2( this.getHours() ) +
                ":" + v2( this.getMinutes() ) + 
                ":" + v2( this.getSeconds() ) +
//              + "." + v2( this.getMilliseconds() ) 
                z;
            return r;
            
        }else{
            var pattern = "^([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
                    "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
                    "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
            var d = s.match( new RegExp( pattern ) );
            if( d && d.length ){
                var offset = 0, time;
                var date = new Date(d[1], 0, 1);
                if (d[3]) { date.setMonth(d[3] - 1); }
                if (d[5]) { date.setDate(d[5]); }
                if (d[7]) { date.setHours(d[7]); }
                if (d[8]) { date.setMinutes(d[8]); }
                if (d[10]) { date.setSeconds(d[10]); }
                if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
                if (d[14]) {
                    offset = (Number(d[16]) * 60) + Number(d[17]);
                    offset *= ((d[15] == '-') ? 1 : -1);
                }
//                offset -= date.getTimezoneOffset();
                time = (Number(date) + (offset * 60 * 1000));
                this.setTime( time );
                return this;
            }else{
                d = new Date( s.replace( /^[A-Za-z]{3},/, "" ) );
            }
            return d;
        }
    }

    var everyday = function ( startDay, endDay, callback )
    {
        startDay.setHours( 0 );
        startDay.setMinutes( 0 );
        startDay.setSeconds( 0 );
        endDay.setHours( 23 );
        endDay.setMinutes( 59 );
        endDay.setSeconds( 59 );

        if( ( endDay - startDay + 1 + 24 * 60 * 60 * 1000 ) >= param.ig ) return null;
        while( startDay < endDay ){
            if( callback.call( startDay, startDay ) === false ) break;
            startDay.setHours( 24 );
        }
        return null;
    }
    
    var drawCalendar = function( date )
    {
        var i, j = 0;
        var tr;

        var today = new Date();
        if( !date ) date = today;
        var d1 = new Date( date.getFullYear(), date.getMonth(), 1 );
        var d2 = new Date( date.getFullYear(), date.getMonth() + 1, 0 );
        var day = ( d1.getDay() + 6 ) % 7;// Mon:0 Tue:1 ... Sut:5 Sun:6
        var node;

        if( date.getFullYear() == today.getFullYear() && date.getMonth() == today.getMonth() )
            today = today.getDate();
        else
            today = 0;

        $( "#calbody" ).empty();
        node = $( "<tr>").appendTo( "#calbody" );
        $( "<th>" ).text( "Mon" ).appendTo( node );
        $( "<th>" ).text( "Tue" ).appendTo( node );
        $( "<th>" ).text( "Wed" ).appendTo( node );
        $( "<th>" ).text( "Thu" ).appendTo( node );
        $( "<th>" ).text( "Fri" ).appendTo( node );
        $( "<th>" ).text( "Sat" ).appendTo( node );
        $( "<th>" ).text( "Sun" ).appendTo( node );
        tr = $( "<tr>" ).appendTo( "#calbody" );
        for( i = 0; i < day; i++, j++ ){
            $( "<td>" ).appendTo( tr );
        }
        for( i = 1; i <= d2.getDate(); i++, j++ ){
            node = $( "<td>" ).appendTo( tr ).text( i ).attr( "id", "cell" + i );
            if( i == today ) node.addClass( "today" );
            if( (j % 7) == 6 ){
                tr = $( "<tr>" ).appendTo( "#calbody" );
            }
        }
        while( (j % 7) != 0 ){
            $( "<td>" ).appendTo( tr );
            j++;
        }
    };


    /* andor : "and" or "or" */
    var getAtnd = function( date, start, keyword, andor )
    {
        if( !date ) date = new Date();
        if( start == null ) start = 0;
        if( keyword == null ) keyword = "";
        if( andor == null ) andor = "and";

        var url = "http://api.atnd.org/events/";
        var param = {
            "start" : start,
            "ym" : date.getFullYear() + v2( date.getMonth() + 1 ),
            "format" : "jsonp"
        };
        var k = ( andor == "and" ) ? "keyword" : "keyword_or";
        param[ k ] = keyword;

        if( start == 1 ){
            $( "#dispyear" ).text( date.getFullYear() );
            $( "#dispmonth" ).text( ( date.getMonth() + 1 ) );
            // append link to atom feed
            (function(){
                if( !keyword ) return;
                var s = /* "&ym=" + param.ym + */ "format=atom";
                $.each( keyword, function(index, value){
                    s += "&" + k + "=" + encodeURIComponent( value );
                } );
                $( "<link>" )
                    .attr( "rel", "alternate" )
                    .attr( "type", "application/atom+xml" )
                    .attr( "title", "Atom Feed(" + param[ k ] + ")" )
                    .attr( "href", url + "?" + s )
                    .appendTo( "#head" );
            })();
        }

        $.ajax( {
            url : url,
            dataType : "jsonp",
            data : param,
            success : function( json ){
                var i;
                if( json.results_returned == 0 ) return false;

                getAtnd( date, json.results_returned + start , keyword, andor );
                if( start == 1 ){
                    $( "#result" ).text( json.results_available );
                }
                var addEvents = function( event ){
                /* event.title; event.event_url; event.startted_at; */
                    var d1 = ( new Date() ).rfc3339( event.started_at );
                    var d2 = ( new Date() ).rfc3339( event.ended_at );
                    everyday( d1, d2, function( day ){
                        if( day.getFullYear() != date.getFullYear() ||
                            day.getMonth() != date.getMonth() ) return;
                        $( "<a>" )
                            .attr( "href", event.event_url )
                            .attr( "target", "_blank" )
                            .attr( "title", event.title + " at " + ( event.place || event.address ) )
                            .text( event.title )
                            .addClass( "event" )
                            .appendTo( $( "<div>" )
                                .addClass( "event" )
                                .appendTo( $( "#cell" + day.getDate())) );

                    } );
                };
                for( i = 0; i < json.results_returned; i++ ){
                    addEvents( json.events[ i ] );
                };
            },
            error : function(){
                alert( "error" );
            } 
        } );

    }

    // parse parameter
    var now = new Date();
    var calmonth = new Date( now.getFullYear(), now.getMonth(), 1 );

    param = {};
    location.search.replace( /[\?&]([^=]+)(=([^&]*))?/g, function( $0, $1, $2, $3 ){ 
        try{
            param[ $1 ] = $2 ? decodeURIComponent( $3 ) : true;
        }catch( e ){
            param[ $1 ] = $2 ? $3 : true;
        }
    } );

    if( param.q !== undefined ){
        $("#q").val( param.q );
    }
    if( param.date !== undefined && param.date.match( /^20[0-9]{2}[0-1][0-9]$/ ) ){
        calmonth = new Date( param.date.substr( 0, 4 ), param.date.substring( 4 ) - 1, 1 );
    }
    if( param.ig !== undefined && param.ig.match( /^[\d]+$/ ) ){
        $("#ig").val( param.ig );
        param.ig = (param.ig | 0) * 24 * 60 * 60 * 1000; 
    }else{
        param.ig = ( $("#ig").val() | 0 ) * 24 * 60 * 60 * 1000;
    }

    var go = function( date ){
        var q = $("#q").val();
        var ig = $("#ig").val() | 0;

        if( date == null ){
            var andor = "or";
            var qq = null;
            if( q ){
                qq = q.split( " OR " );
                if( qq.length == 1 ){
                    qq = q.split( " " );
                    andor = "and";
                }
            }
            getAtnd( calmonth, 1, qq, andor );
        }else{
            var url;
            url = location.href.replace( /\?.*/, "" ) + "?date=" + date.getFullYear() + v2( date.getMonth() + 1 );
            if( ig !== undefined ) url += "&ig=" + ig;
            if( q ) url += "&q=" + encodeURIComponent( q );
            location.href = url;
        }
        return false;
    };
    
    $( "#prev" ).click( function(){
        calmonth.setMonth( calmonth.getMonth() - 1 );
        return go( calmonth );
    } );
    $( "#next" ).click( function(){
        calmonth.setMonth( calmonth.getMonth() + 1 );
        return go( calmonth );
    } );
    $( "#today" ).click( function(){
        var now = new Date();
        calmonth = new Date( now.getFullYear(), now.getMonth(), 1 );
        return go( calmonth );
    } );
    $( "#form" ).submit( function(){
        if( $( "#q" ).val().match( /<script[^a-zA-Z0-9]/ ) ){
            alert( "通報しますた" );
            return false;
        }
        return go( calmonth );
    } );

    drawCalendar( calmonth );
    go();


} );





