
var Directory = function(widget_el)
{
    var self = this;

    this.prefix = 'directory:';

    this.section = false;
    this.sortby = false;
    this.sort_reverse = false;

    this.categories = {};
    this.areas = {};
    this.suburbs = {};

    this.data = [
        ['cat','categories','category'],
        ['suburb','suburbs','suburb'],
        ['area','areas','area']
    ];

    this.queryString = '';
    this.queryLoading = false;

    $('.heading', widget_el).click(function()
    {
        self.open();
    });
    $('.section', widget_el).click(function()
    {
        self.section = $(this).attr('name') || false;
        self.open();
    });

    this.check_hash(true);
};
Directory.prototype.serialize = function()
{
    var self = this;

    var parts = [];

    parts.push(this.section || '');
    parts.push(this.sortby || '');

    $.each(this.data, function(i, d)
    {
        var dpart = [];
        $.each(self[d[1]], function(k, v)
        {
            if (k == v)
                dpart.push(v);
            else
                dpart.push(k+'='+v);
        });
        parts.push(dpart.join('&'));
    });

    return this.prefix+parts.join('&&');
};
Directory.prototype.unserialize = function(str)
{
    var self = this;

    str = this.has_prefix(str);
    if (!str)
        return;

    var parts = str.split('&&');
    if (parts.length != this.data.length + 2)
        return;

    this.section = parts.shift() || false;
    this.sortby = parts.shift() || false;

    $.each(this.data, function(i, d)
    {
        self[d[1]] = {};
        var dparts = parts.shift().split('&');
        $.each(dparts, function(i, kv)
        {
            if (!kv)
                return;
            kv = kv.split('=');
            var k = kv[0], 
                v = kv[0];
            if (kv.length == 2)
                var v = kv[1];
            self[d[1]][k] = v;
        });
    });
};
Directory.prototype.has_prefix = function(str)
{
    if (str.substr(0, this.prefix.length) == this.prefix)
        return str.substr(this.prefix.length);
    return false;
};
Directory.prototype.check_hash = function(start)
{
    var self = this;
    var cur_hash = start?false:window.location.hash;
    clearInterval(this.check_hash_timer);

    this.check_hash_timer = setInterval(function()
    {
        if (window.location.hash == cur_hash)
            return;
        cur_hash = window.location.hash;

        if (cur_hash == '#' || !cur_hash)
            return self.close();

        var hash = cur_hash.substr(1);
        if (!self.has_prefix(hash))
            return;

        self.unserialize(hash);
        if (!self.element)
            self.open();
        else
            self.update(true);

    }, 500);
};
Directory.prototype.open = function()
{
    var self = this;

    this.element = $(
        '<div class="directory-container'+
            (this.section?'':' sections-only')+'">'+
            '<div class="directory-bg" />'+
            '<div class="directory-content">'+
                '<div class="directory-loading" />'+
            '</div>'+
        '</div>')
        .appendTo('body');

    $.ajax({
        url: '/directory',
        method: 'GET',
        dataType: 'html',
        success: function(html)
        {
            self.element.find('.directory-content').html(html);
            $('body > .container').hide();
            _typeface_js.renderDocument();
            self.bindEvents();
            self.update();
            self.query();
            self.check_hash();
        }
    });
};
Directory.prototype.close = function()
{
    window.location.hash = '';
    if (this.element)
        this.element.remove();
    this.element = false;
    $('body > .container').show();
    $(window).unbind('keypress');
};
Directory.prototype.bindEvents = function()
{
    var self = this;

    this.results_el = this.element.find('.results-container');

    this.search = new Search(
        this.element.find('.searchbox input'), null, 
        'Type search term here');
    this.search.query = function(query)
    {
        self.queryString = query;
        self.update();
        self.query();
    };
    this.search.clear = function() { };

    this.element.find('.categories .datum').click(function()
    {
        var $el = $(this);
        $.each(self.data, function(i, d)
        {
            var id = $el.attr(d[0]);
            if (!id)
                return;
            var name = $el.attr('name') || $el.text();
            if ($el.is('.selected'))
                delete self[d[1]][id];
            else
            {
                if (d[1] == 'areas' || d[1] == 'suburbs')
                {
                    self['areas'] = {}
                    self['suburbs'] = {}
                }
                self[d[1]][id] = name;
            }
        });
        self.update();
        self.query();
    });

    this.element.find('.criteria, .results .header').click(function(e) 
    {
        var changed = false;
        var $el = $(e.target).closest('.sub');

        $.each(self.data, function(i, d)
        {
            var v = $el.attr(d[0]);
            if (v)
            {
                changed = true;
                delete self[d[1]][v];
            }
        });

        if ($el.attr('sect'))
        {
            changed = true;
            self.section = false;
        }

        if ($el.attr('sort'))
        {
            var sort = $el.attr('sort');
            if (sort == 'none')
            {
                self.sortby = false;
                self.sort_reverse = false;
            }
            else if (sort == self.sortby)
            {
                self.sort_reverse = !self.sort_reverse;
            }
            else
            {
                self.sortby = sort;
                self.sort_reverse = false;
            }
            changed = true;
        }

        if ($el.attr('query'))
        {
            changed = true;
            self.search.setInactive();
            self.queryString = '';
        }

        if (changed)
        {
            self.update();
            self.query();
        }
    });

    this.element.find('.sections a').click(function()
    {
        var id = $(this).attr('name');
        if (self.section == id)
            self.section = false;
        else
            self.section = id;

        // reset criteria
        $.each(self.data, function(i, d) {
            self[d[1]] = {};
        });
        self.sortby = false;
        self.sort_reverse = false;

        self.update();
        self.query();
    });

    this.element.find('.close, .masthead').click(function()
    {
        self.close();
    });

    $(window).keypress(function(e) {
        if (e.keyCode == 27)
            self.close();
    });
};
Directory.prototype.update = function(no_set_hash)
{
    var self = this;

    if (this.section)
        this.element.removeClass('sections-only');
    else
        this.element.addClass('sections-only');

    // highlight selected section
    var section_title = false;
    this.element.find('.sections a').each(function()
    {
        if (self.section == $(this).attr('name'))
        {
            $(this).addClass('selected');
            section_title = $(this).attr('title');
        }
        else
            $(this).removeClass('selected');
    });

    // hide Areas for events
    this.element.find('.categories > .header, .categories > .datum')[(self.section == 'event')?'hide':'show']();

    // hide all categories that don't belong in this section
    this.element.find('.categories .category').each(function()
    {
        var sections = $(this).attr('sections');
        if (!sections)
            return;
        if (!section_title)
        {
            $(this).show();
            return;
        }
        if ($.inArray(section_title, sections.split('/')) === -1)
            $(this).hide();
        else
            $(this).show();
    });

    var suburb_visible = false;
    var $suburbs = self.element.find('.categories .suburb')
    function show_suburbs(area)
    {
        var selector = '[parent='+area+']';
        $suburbs.not(selector).hide();
        $suburbs.filter(selector).show();
        suburb_visible = true;
    }

    // highlight selected categories
    this.element.find('.categories .datum').each(function()
    {
        var $el = $(this);
        $.each(self.data, function(i, d)
        {
            var id = $el.attr(d[0]);
            if (!id)
                return;
            if (self[d[1]][id])
            {
                $el.addClass('selected');
                if (d[1] == 'areas')
                    show_suburbs(id);
                if (d[1] == 'suburbs')
                    show_suburbs($el.attr('parent'));
            }
            else
                $el.removeClass('selected');
        });
    });

    if (!suburb_visible)
        $suburbs.hide();

    // draw criteria list
    var criteria = '';
    var x = '<img class="x" src="/media/layout/criteria-x.gif" />';

    // query
    if (this.queryString)
        criteria+= '<div class="sub" query="true">'+x+'Search term</div>';

    // section
    if (this.section)
        criteria+= '<div class="sub" sect="true">'+x+section_title+'</div>';

    // other criteria
    $.each(this.data, function(i, d)
    {
        for (id in self[d[1]])
        {
            displayname = self[d[1]][id];
            if (d[1] == 'categories')
                displayname = displayname.split('-')[1];
            criteria+= '<div class="sub" '+d[0]+'="'+id+'">'+
                x+ displayname +'</div>';
        }
    });
    if (this.sortby) 
        criteria+= '<div class="sub" sort="none">'+x+'Remove Sort</div>';
    this.element.find('.criteria-container').empty().html(criteria);

    // sort order
    this.element.find('.sort .sub').each(function()
    {
        var sort = $(this).attr('sort');
        if (sort == self.sortby)
            $(this).addClass('selected');
        else
            $(this).removeClass('selected');
    });

    if (!no_set_hash)
    {
        window.location.hash = this.serialize();
        this.check_hash();
    }
};
Directory.prototype.query = function()
{
    var self = this;

    var query = '';

    // data
    $.each(this.data, function(i, d)
    {
        for (id in self[d[1]])
        {
            var v = self[d[1]][id].replace(/ /, '-');
            query+= d[2]+':'+v+' ';
        }
    });
    // searchbox 
    query+= this.queryString;
    // section
    if (this.section)
        query = 'section:'+this.section+' ' + query;

    if (!query)
    {
        this.results_el.empty();
        return;
    }

    this.queryLoading = query;
    var spinner = this.element.find('.spinner').show();

    var sort = this.sortby || '';
    if (this.sort_reverse && sort)
        sort = (sort[0] != '-') ?'-'+sort :sort.substr(1);

    $.ajax({
        url: '/search',
        method: 'GET',
        data: { a: 1, d: 1, q: query, s: sort },
        dataType: 'html',
        success: function(html)
        {
            if (self.queryLoading != query)
                return;
            self.queryLoading = false;
            spinner.hide();
            self.results_el.html(html);
        }
    });
};

