function CategoryControl()
{
    this.holder     = null;
    this.categories = null;
    this.levels     = [];
    this.category   = null;
    this.def        = null;
}

with ( { _ : CategoryControl.prototype } )
{
    _.init = function (holder, categories, output)
    {
        this.holder = holder;
        this.output = output;
        //this.addCategorySelect(0, categories);
        //this.onCategoryChanged(0);
    }

    _.remove = function ()
    {
    }

    _.setDefaultValue = function (def)
    {
        this.def = def;
    }

    _.setChain = function (chain)
    {
        this.chain = chain;
        this.setChainValue(0);
    }

    _.setChainValue = function (level)
    {
        var d = $.getJSON("/ajax/categories/",
            (level > 0) ? {parent:this.levels[level - 1][0].val()} : "",
            $.bind(this, this.setChainValue_cont, level)
        );
    }

    _.setChainValue_cont = function (level, data)
    {
        this.addCategorySelect(level, data);
        this.levels[level][0].get(0).value = this.chain[level];
        if ( level + 1 < this.chain.length )
        {
            this.setChainValue(level + 1);
        }
        else
        {
            this.onCategoryChanged(level);
        }
    }

    _.onCategoryChanged = function (level)
    {
        while ( level < this.levels.length - 1 )
        {
            this.removeCategorySelect(this.levels.length - 1);
            this.levels.length = this.levels.length - 1;
        }
        if ( this.output )
        {
            this.output.val(this.getCategory());
        }
        this.getSubcategories(this.getCategory(level), level);
    }

    _.getSubcategories = function (categoryId, level)
    {
        if ( categoryId == 0 )
        {
            this.onCategoriesFetched(level, []);
            return;
        }

        for ( var i = 0; i < this.levels.length; i++ )
        {
            this.levels[i][0].attr("disabled", true);
        }
        var d = $.getJSON("/ajax/categories/",
            {parent:categoryId},
            $.bind(this, this.onCategoriesFetched, level)
        );
    }

    _.onCategoriesFetched = function (level, categories)
    {
        for ( var i = 0; i < this.levels.length; i++ )
        {
            this.levels[i][0].removeAttr("disabled");
        }
        if ( categories.length > 0 )
        {
            this.addCategorySelect(level + 1, categories);
        }
    }

    _.getCategory = function (level)
    {
        var v = this.levels[this.levels.length - 1][0].val();
        if ( level != undefined )
        {
            return this.levels[level][0].val();
        }
        else
        {
            var i = this.levels.length - 2;
            while ( i >= 0 && (v == '' || v == 0) )
            {
                v = this.levels[i][0].val();
                i -= 1;
            }
        }
        return v;
    }

    _.addCategorySelect = function (level, categories, value)
    {
        var p = null;
        if ( level > 0 )
        {
            p = $("<span>Подкатегория:</span>").appendTo(this.holder);
        }
        var s = $("<select></select>")
            .appendTo(this.holder);
        this.levels[level] = [s, p];
        if ( level > 0 )
        {
            $("<option></option>")
                .attr("value", 0)
                .text("...")
                .appendTo(s);
        }
        if ( level == 0 && this.def )
        {
            $("<option></option>")
                .attr("value", '')
                .text(this.def)
                .appendTo(s);
        }
        for ( var i = 0; i < categories.length; i++ )
        {
            var c = categories[i];
            $("<option></option>")
                .attr("value", c[0])
                .text(c[1])
                .appendTo(s);
        }
        if ( value )
        {
            s.val(value);
        }
        s.change($.bind(this, this.onCategoryChanged, level));
    }

    _.removeCategorySelect = function (level)
    {
        this.levels[level][0].remove();
        if ( level > 0 )
        {
            this.levels[level][1].remove();
        }
    }
}

