    /* @private
     * Currently not used
     * Rrule info: http://www.kanzaki.com/docs/ical/rrule.html
     */
    Ext.ensible.cal.RecurrenceField = Ext.extend(Ext.form.Field, {

        fieldLabel: 'Repeats',
        startDate: new Date().clearTime(),
        enableFx: true,

        initComponent : function(){
            Ext.ensible.cal.RecurrenceField.superclass.initComponent.call(this);
            if(!this.height){
                this.autoHeight = true;
            }
        },

        onRender: function(ct, position){
            if(!this.el){
                this.frequencyCombo = new Ext.ensible.cal.RecurrenceCombo({
                    id: this.id+'-frequency',
                    listeners: {
                        'recurrencechange': {
                            fn: this.showOptions,
                            scope: this
                        }
                    }
                });
                if(this.fieldLabel){
                    this.frequencyCombo.fieldLabel = this.fieldLabel;
                }

                this.innerCt = new Ext.Container({
                    cls: 'extensible-recur-inner-ct',
                    items: []
                });
                this.fieldCt = new Ext.Container({
                    autoEl: {id:this.id}, //make sure the container el has the field's id
                    cls: 'extensible-recur-ct',
                    renderTo: ct,
                    items: [this.frequencyCombo, this.innerCt]
                });

                this.fieldCt.ownerCt = this;
                this.innerCt.ownerCt = this.fieldCt;
                this.el = this.fieldCt.getEl();
                this.items = new Ext.util.MixedCollection();
                this.items.addAll(this.initSubComponents());
            }
            Ext.ensible.cal.RecurrenceField.superclass.onRender.call(this, ct, position);
        },

    //    afterRender : function(){
    //        Ext.ensible.cal.RecurrenceField.superclass.afterRender.call(this);
    //        this.setStartDate(this.startDate);
    //    },

        // private
        initValue : function(){
            this.setStartDate(this.startDate);

            if(this.value !== undefined){
                this.setValue(this.value);
            }
            else if(this.frequency !== undefined){
                this.setValue('FREQ='+this.frequency);
            }
            else{
                this.setValue('NONE');
            }
            this.originalValue = this.getValue();
        },

        showOptions : function(o){
            var layoutChanged = false, unit = 'day';

            if(o != 'NONE'){
                this.hideSubPanels();
            }
            this.frequency = o;

            switch(o){
                case 'DAILY':
                    layoutChanged = this.showSubPanel(this.repeatEvery);
                    layoutChanged |= this.showSubPanel(this.until);
                    break;

                case 'WEEKLY':
                    layoutChanged = this.showSubPanel(this.repeatEvery);
                    layoutChanged |= this.showSubPanel(this.weekly);
                    layoutChanged |= this.showSubPanel(this.until);
                    unit = 'week';
                    break;

                case 'MONTHLY':
                    layoutChanged = this.showSubPanel(this.repeatEvery);
                    layoutChanged |= this.showSubPanel(this.monthly);
                    layoutChanged |= this.showSubPanel(this.until);
                    unit = 'month';
                    break;

                case 'YEARLY':
                    layoutChanged = this.showSubPanel(this.repeatEvery);
                    layoutChanged |= this.showSubPanel(this.yearly);
                    layoutChanged |= this.showSubPanel(this.until);
                    unit = 'year';
                    break;

                default:
                    // case NONE
                    this.hideInnerCt();
                    return;
            }

            if(layoutChanged){
                this.innerCt.doLayout();
            }

            this.showInnerCt();
            this.repeatEvery.updateLabel(unit);
        },

        showSubPanel : function(p){
            if (p.rendered) {
                p.show();
                return false;
            }
            else{
                if(this.repeatEvery.rendered){
                    // make sure weekly/monthly options show in the middle
                    p = this.innerCt.insert(1, p);
                }
                else{
                    p = this.innerCt.add(p);
                }
                p.show();
                return true;
            }
        },

        showInnerCt: function(){
            if(!this.innerCt.isVisible()){
                if(this.enableFx && Ext.enableFx){
                    this.innerCt.getPositionEl().slideIn('t', {
                        duration: .3
                    });
                }
                else{
                    this.innerCt.show();
                }
            }
        },

        hideInnerCt: function(){
            if(this.innerCt.isVisible()){
                if(this.enableFx && Ext.enableFx){
                    this.innerCt.getPositionEl().slideOut('t', {
                        duration: .3,
                        easing: 'easeIn',
                        callback: this.hideSubPanels,
                        scope: this
                    });
                }
                else{
                    this.innerCt.hide();
                    this.hideSubPanels();
                }
            }
        },

        setStartDate : function(dt){
            this.items.each(function(p){
                p.setStartDate(dt);
            });
        },

        getValue : function(){
            if(!this.rendered) {
                return this.value;
            }
            if(this.frequency=='NONE'){
                return '';
            }
            var value = 'FREQ='+this.frequency;
            this.items.each(function(p){
                if(p.isVisible()){
                    value += p.getValue();
                }
            });
            return value;
        },

        setValue : function(v){
            this.value = v;

            if(v == null || v == '' || v == 'NONE'){
                this.frequencyCombo.setValue('NONE');
                this.showOptions('NONE');
                return this;
            }
            var parts = v.split(';');
            this.items.each(function(p){
                p.setValue(parts);
            });
            Ext.each(parts, function(p){
                if(p.indexOf('FREQ') > -1){
                    var freq = p.split('=')[1];
                    this.frequencyCombo.setValue(freq);
                    this.showOptions(freq);
                    return;
                }
            }, this);

            return this;
        },

        hideSubPanels : function(){
            this.items.each(function(p){
                p.hide();
            });
        },

        initSubComponents : function(){
            Ext.ensible.cal.recurrenceBase = Ext.extend(Ext.Container, {
                fieldLabel: ' ',
                labelSeparator: '',
                hideLabel: true,
                layout: 'table',
                anchor: '100%',
                startDate: this.startDate,

                //TODO: This is not I18N-able:
                getSuffix : function(n){
                    if(!Ext.isNumber(n)){
                        return '';
                    }
                    switch (n) {
                        case 1:
                        case 21:
                        case 31:
                            return "st";
                        case 2:
                        case 22:
                            return "nd";
                        case 3:
                        case 23:
                            return "rd";
                        default:
                            return "th";
                    }
                },

                //shared by monthly and yearly components:
                initNthCombo: function(cbo){
                    var cbo = Ext.getCmp(this.id+'-combo'),
                        dt = this.startDate,
                        store = cbo.getStore(),
                        last = dt.getLastDateOfMonth().getDate(),
                        dayNum = dt.getDate(),
                        nthDate = dt.format('jS') + ' day',
                        isYearly = this.id.indexOf('-yearly') > -1,
                        yearlyText = ' in ' + dt.format('F'),
                        nthDayNum, nthDay, lastDay, lastDate, idx, data, s;

                    nthDayNum = Math.ceil(dayNum / 7);
                    nthDay = nthDayNum + this.getSuffix(nthDayNum) + dt.format(' l');
                    if(isYearly){
                        nthDate += yearlyText;
                        nthDay += yearlyText;
                    }
                    data = [[nthDate],[nthDay]];

                    s = isYearly ? yearlyText : '';
                    if(last-dayNum < 7){
                        data.push(['last '+dt.format('l')+s]);
                    }
                    if(last == dayNum){
                        data.push(['last day'+s]);
                    }

                    idx = store.find('field1', cbo.getValue());
                    store.removeAll();
                    cbo.clearValue();
                    store.loadData(data);

                    if(idx > data.length-1){
                        idx = data.length-1;
                    }
                    cbo.setValue(store.getAt(idx > -1 ? idx : 0).data.field1);
                    return this;
                },
                setValue:Ext.emptyFn
            });

            this.repeatEvery = new Ext.ensible.cal.recurrenceBase({
                id: this.id+'-every',
                layoutConfig: {
                    columns: 3
                },
                items: [{
                    xtype: 'label',
                    text: 'Repeat every'
                },{
                    xtype: 'numberfield',
                    id: this.id+'-every-num',
                    value: 1,
                    width: 35,
                    minValue: 1,
                    maxValue: 99,
                    allowBlank: false,
                    enableKeyEvents: true,
                    listeners: {
                        'keyup': {
                            fn: function(){
                                this.repeatEvery.updateLabel();
                            },
                            scope: this
                        }
                    }
                },{
                    xtype: 'label',
                    id: this.id+'-every-label'
                }],
                setStartDate: function(dt){
                    this.startDate = dt;
                    this.updateLabel();
                    return this;
                },
                getValue: function(){
                    var v = Ext.getCmp(this.id+'-num').getValue();
                    return v > 1 ? ';INTERVAL='+v : '';
                },
                setValue : function(v){
                    var set = false,
                        parts = Ext.isArray(v) ? v : v.split(';');

                    Ext.each(parts, function(p){
                        if(p.indexOf('INTERVAL') > -1){
                            var interval = p.split('=')[1];
                            Ext.getCmp(this.id+'-num').setValue(interval);
                        }
                    }, this);
                    return this;
                },
                updateLabel: function(type){
                    if(this.rendered){
                        var s = Ext.getCmp(this.id+'-num').getValue() == 1 ? '' : 's';
                        this.type = type ? type.toLowerCase() : this.type || 'day';
                        var lbl = Ext.getCmp(this.id+'-label');
                        if(lbl.rendered){
                            lbl.update(this.type + s + ' beginning ' + this.startDate.format('l, F j'));
                        }
                    }
                    return this;
                },
                afterRender: function(){
                    Ext.ensible.cal.recurrenceBase.superclass.afterRender.call(this);
                    this.updateLabel();
                }
            });

            this.weekly = new Ext.ensible.cal.recurrenceBase({
                id: this.id+'-weekly',
                layoutConfig: {
                    columns: 2
                },
                items: [{
                    xtype: 'label',
                    text: 'on:'
                },{
                    xtype: 'checkboxgroup',
                    id: this.id+'-weekly-days',
                    items: [
                        {boxLabel: 'Sun', name: 'SU', id: this.id+'-weekly-SU'},
                        {boxLabel: 'Mon', name: 'MO', id: this.id+'-weekly-MO'},
                        {boxLabel: 'Tue', name: 'TU', id: this.id+'-weekly-TU'},
                        {boxLabel: 'Wed', name: 'WE', id: this.id+'-weekly-WE'},
                        {boxLabel: 'Thu', name: 'TH', id: this.id+'-weekly-TH'},
                        {boxLabel: 'Fri', name: 'FR', id: this.id+'-weekly-FR'},
                        {boxLabel: 'Sat', name: 'SA', id: this.id+'-weekly-SA'}
                    ]
                }],
                setStartDate: function(dt){
                    this.startDate = dt;
                    this.selectToday();
                    return this;
                },
                selectToday: function(){
                    this.clearValue();
                    var day = this.startDate.format('D').substring(0,2).toUpperCase();
                    Ext.getCmp(this.id + '-days').setValue(day, true);
                },
                clearValue: function(){
                    Ext.getCmp(this.id + '-days').setValue([false, false, false, false, false, false, false]);
                },
                getValue: function(){
                    var v = '', sel = Ext.getCmp(this.id+'-days').getValue();
                    Ext.each(sel, function(chk){
                        if(v.length > 0){
                            v += ',';
                        }
                        v += chk.name;
                    });
                    var day = this.startDate.format('D').substring(0,2).toUpperCase();
                    return v.length > 0 && v != day ? ';BYDAY='+v : '';
                },
                setValue : function(v){
                    var set = false,
                        parts = Ext.isArray(v) ? v : v.split(';');

                    this.clearValue();

                    Ext.each(parts, function(p){
                        if(p.indexOf('BYDAY') > -1){
                            var days = p.split('=')[1].split(','),
                                vals = {};

                            Ext.each(days, function(d){
                                vals[d] = true;
                            }, this);

                            Ext.getCmp(this.id+'-days').setValue(vals);
                            return set = true;
                        }
                    }, this);

                    if(!set){
                        this.selectToday();
                    }
                    return this;
                }
            });

            this.monthly = new Ext.ensible.cal.recurrenceBase({
                id: this.id+'-monthly',
                layoutConfig: {
                    columns: 3
                },
                items: [{
                    xtype: 'label',
                    text: 'on the'
                },{
                    xtype: 'combo',
                    id: this.id+'-monthly-combo',
                    mode: 'local',
                    width: 150,
                    triggerAction: 'all',
                    forceSelection: true,
                    store: []
                },{
                    xtype: 'label',
                    text: 'of each month'
                }],
                setStartDate: function(dt){
                    this.startDate = dt;
                    this.initNthCombo();
                    return this;
                },
                getValue: function(){
                    var cbo = Ext.getCmp(this.id+'-combo'),
                        store = cbo.getStore(),
                        idx = store.find('field1', cbo.getValue()),
                        dt = this.startDate,
                        day = dt.format('D').substring(0,2).toUpperCase();

                    if (idx > -1) {
                        switch(idx){
                            case 0:  return ';BYMONTHDAY='+dt.format('j');
                            case 1:  return ';BYDAY='+cbo.getValue()[0].substring(0,1)+day;
                            case 2:  return ';BYDAY=-1'+day;
                            default: return ';BYMONTHDAY=-1';
                        }
                    }
                    return '';
                }
            });

            this.yearly = new Ext.ensible.cal.recurrenceBase({
                id: this.id+'-yearly',
                layoutConfig: {
                    columns: 3
                },
                items: [{
                    xtype: 'label',
                    text: 'on the'
                },{
                    xtype: 'combo',
                    id: this.id+'-yearly-combo',
                    mode: 'local',
                    width: 170,
                    triggerAction: 'all',
                    forceSelection: true,
                    store: []
                },{
                    xtype: 'label',
                    text: 'each year'
                }],
                setStartDate: function(dt){
                    this.startDate = dt;
                    this.initNthCombo();
                    return this;
                },
                getValue: function(){
                    var cbo = Ext.getCmp(this.id+'-combo'),
                        store = cbo.getStore(),
                        idx = store.find('field1', cbo.getValue()),
                        dt = this.startDate,
                        day = dt.format('D').substring(0,2).toUpperCase(),
                        byMonth = ';BYMONTH='+dt.format('n');

                    if(idx > -1){
                        switch(idx){
                            case 0:  return byMonth;
                            case 1:  return byMonth+';BYDAY='+cbo.getValue()[0].substring(0,1)+day;
                            case 2:  return byMonth+';BYDAY=-1'+day;
                            default: return byMonth+';BYMONTHDAY=-1';
                        }
                    }
                    return '';
                }
            });

            this.until = new Ext.ensible.cal.recurrenceBase({
                id: this.id+'-until',
                untilDateFormat: 'Ymd\\T000000\\Z',
                layoutConfig: {
                    columns: 5
                },
                items: [{
                    xtype: 'label',
                    text: 'and continuing'
                },{
                    xtype: 'combo',
                    id: this.id+'-until-combo',
                    mode: 'local',
                    width: 85,
                    triggerAction: 'all',
                    forceSelection: true,
                    value: 'forever',
                    store: ['forever', 'for', 'until'],
                    listeners: {
                        'select': {
                            fn: function(cbo, rec){
                                var dt = Ext.getCmp(this.id+'-until-date');
                                if(rec.data.field1 == 'until'){
                                    dt.show();
                                    if (dt.getValue() == '') {
                                        dt.setValue(this.startDate.add(Date.DAY, 5));
                                        dt.setMinValue(this.startDate.clone().add(Date.DAY, 1));
                                    }
                                }
                                else{
                                    dt.hide();
                                }
                                if(rec.data.field1 == 'for'){
                                    Ext.getCmp(this.id+'-until-num').show();
                                    Ext.getCmp(this.id+'-until-endlabel').show();
                                }
                                else{
                                    Ext.getCmp(this.id+'-until-num').hide();
                                    Ext.getCmp(this.id+'-until-endlabel').hide();
                                }
                            },
                            scope: this
                        }
                    }
                },{
                    xtype: 'datefield',
                    id: this.id+'-until-date',
                    showToday: false,
                    hidden: true
                },{
                    xtype: 'numberfield',
                    id: this.id+'-until-num',
                    value: 5,
                    width: 35,
                    minValue: 1,
                    maxValue: 99,
                    allowBlank: false,
                    hidden: true
                },{
                    xtype: 'label',
                    id: this.id+'-until-endlabel',
                    text: 'occurrences',
                    hidden: true
                }],
                setStartDate: function(dt){
                    this.startDate = dt;
                    return this;
                },
                getValue: function(){
                    var dt = Ext.getCmp(this.id+'-date');
                    if(dt.isVisible()){
                        return ';UNTIL='+dt.getValue().format(this.untilDateFormat);
                    }
                    var ct = Ext.getCmp(this.id+'-num');
                    if(ct.isVisible()){
                        return ';COUNT='+ct.getValue();
                    }
                    return '';
                },
                setValue : function(v){
                    var set = false,
                        parts = Ext.isArray(v) ? v : v.split(';');

                    Ext.each(parts, function(p){
                        if(p.indexOf('COUNT') > -1){
                            var count = p.split('=')[1];
                            Ext.getCmp(this.id+'-combo').setValue('for');
                            Ext.getCmp(this.id+'-num').setValue(count).show();
                            Ext.getCmp(this.id+'-endlabel').show();
                        }
                        else if(p.indexOf('UNTIL') > -1){
                            var dt = p.split('=')[1];
                            Ext.getCmp(this.id+'-combo').setValue('until');
                            Ext.getCmp(this.id+'-date').setValue(Date.parseDate(dt, this.untilDateFormat)).show();
                            Ext.getCmp(this.id+'-endlabel').hide();
                        }
                    }, this);
                    return this;
                }
            });

            return [this.repeatEvery, this.weekly, this.monthly, this.yearly, this.until];
        }
    });

    Ext.reg('extensible.recurrencefield', Ext.ensible.cal.RecurrenceField);