var CrontabTimeUnityNotationType={SingleExpression:0,Range:1,List:2,Every:3,Interval:4,Unknown:5};
var CrontabTimeUnityType={Minutes:"Minutes",Hours:"Hours",MonthDays:"MonthDays",Monthes:"Monthes",WeekDays:"WeekDays"};
CrontabManager = {
    Parse:function(crontabExpr) {
        thisCtExpr = new CrontabExpression();
        thisCtExpr.Parse(crontabExpr);
        return thisCtExpr;
    }
}
function CrontabExpression() {
    var _thisExpr=null;
    function CrontabTimeUnity(unityType,expr,minInterval,maxInterval) {
        this.IsValid=true;
        this.ErrorMessage="";
        this.Expression=expr;
        this.Values=[];
        this.ValuesToString=function(unitFormat,convertor) {
            var valStr = "";
            for(var x=0;x<this.Values.length;x++) {
                if((x>0) && (x==this.Values.length-1)) valStr+= " et ";
                if(convertor!=null) valStr += convertor(this.Values[x]);
                else valStr += this.Values[x];
                if((unitFormat!=null) && (unitFormat!="")) valStr+=unitFormat;
                if((this.Values.length>1) && (x<this.Values.length-2)) valStr +=", ";
            }
            return valStr;
        }
        this.NotationType=CrontabTimeUnityNotationType.Unknown;
        var re = new RegExp();
        if(re.compile("^,").test(expr) || re.compile(",$").test(expr)) {
            this.ErrorMessage="Error in "+unityType+" unity expression: start or finish with coma";
            this.IsValid=false;
        }
        if(this.IsValid) { 
            if(re.compile("^(\\d+)\\-(\\d+)$").test(expr)) {
                this.NotationType = CrontabTimeUnityNotationType.Range;
                var startRange = parseInt(RegExp.$1);var endRange = parseInt(RegExp.$2);
                if(startRange >= endRange) {
                    if(startRange==endRange) expr=startRange;
                    else {                    
                        this.ErrorMessage="Error in "+unityType+" unity expression: range start number must be smaller than range end number";
                        this.IsValid=false;
                    }
                }
                else {
                    var parts=expr.split("-");
                    var start=parseInt(parts[0]);
                    var end=parseInt(parts[1]);
                    if((start<minInterval) || (end>maxInterval)) {
                        this.ErrorMessage="Error in "+unityType+" unity expression: out of range parameters";
                        this.IsValid=false;
                    }
                    else {
                        for(var x=start;x<=end;x++) {
                            this.Values[this.Values.length]=x;
                        }
                    }
                }
            }
            else if(re.compile("^\\d{1,2}$").test(expr)) {
                this.NotationType = CrontabTimeUnityNotationType.SingleExpression;
                this.Values[0]=parseInt(expr);
                if((this.Values[0]<minInterval) || (this.Values[0]>maxInterval)) {
                    this.ErrorMessage="Error in "+unityType+" unity expression: out of range parameters";
                    this.IsValid=false;
                }
                
            }
            else if(re.compile("^\\*$").test(expr)) this.NotationType = CrontabTimeUnityNotationType.Every;
            else if(re.compile("^\\d+((,\\d+)+)$").test(expr)) {
                this.NotationType = CrontabTimeUnityNotationType.List;
                this.Values=this.Expression.split(",");
                for(var x=0;x<this.Values.length;x++) {
                    if((this.Values[x]<minInterval) || (this.Values[x]>maxInterval)) {
                        this.ErrorMessage="Error in "+unityType+" unity expression: out of range parameters";
                        this.IsValid=false;
                    }
                }                
            }
            else if(re.compile("^\\*/\\d{1,2}$").test(expr)) {
                this.NotationType = CrontabTimeUnityNotationType.Interval;
                var inc = parseInt(this.Expression.replace("*/",""));
                if(arguments.length==4) {
                    for(var x=minInterval;x<=maxInterval;x+=inc) {
                        this.Values[this.Values.length] = x;
                    }
                }
                else {
                    if((inc<minInterval) || (inc>maxInterval)) {
                        this.ErrorMessage="Error in "+unityType+" unity expression: out of range parameters";
                        this.IsValid=false;
                    }
                    else this.Values[this.Values.length] = inc;
                }
            }
            else if(this.NotationType==CrontabTimeUnityNotationType.Unknown) {
                this.IsValid=false;
                this.ErrorMessage="Error in "+unityType+" unity expression: unknown notation type";
            }
        }
    }
    this.Units={Minutes:null,Hours:null,MonthDays:null,Monthes:null,WeekDays:null};
    this.ErrorMessage = "";this.IsValid=true;
    this.Parse=function(expr) {
        _thisExpr=expr;
        var re = new RegExp();
        if(re.compile("^(\\S+)\\s(\\S+)\\s(\\S+)\\s(\\S+)\\s(\\S+)$").test(expr)) {
             var minutes=RegExp.$1;var hours=RegExp.$2;var monthDays=RegExp.$3;var monthes=RegExp.$4;var weekDays=RegExp.$5;
             this.Units.Minutes = new CrontabTimeUnity(CrontabTimeUnityType.Minutes,minutes,0,59);
             this.Units.Hours = new CrontabTimeUnity(CrontabTimeUnityType.Hours,hours,0,23);
             this.Units.MonthDays = new CrontabTimeUnity(CrontabTimeUnityType.MonthDays,monthDays,1,31);
             this.Units.Monthes = new CrontabTimeUnity(CrontabTimeUnityType.Monthes,monthes,1,12);
             this.Units.WeekDays = new CrontabTimeUnity(CrontabTimeUnityType.WeekDays,weekDays,0,6);                 
             if(!this.Units.Minutes.IsValid) this.ErrorMessage+=this.Units.Minutes.ErrorMessage+"\n";
             if(!this.Units.Hours.IsValid) this.ErrorMessage+=this.Units.Hours.ErrorMessage+"\n";
             if(!this.Units.MonthDays.IsValid) this.ErrorMessage+=this.Units.MonthDays.ErrorMessage+"\n";
             if(!this.Units.Monthes.IsValid) this.ErrorMessage+=this.Units.Monthes.ErrorMessage+"\n";
             if(!this.Units.WeekDays.IsValid) this.ErrorMessage+=this.Units.WeekDays.ErrorMessage+"\n";
             if(this.ErrorMessage!="") this.IsValid=false;
        }
        else {
            this.IsValid=false;
            this.ErrorMessage="Error in Crontab: invalid syntax. Check white spaces or incomplete expression."; 
        }
    };
    this.Translate=function() {
        if(this.IsValid) {
            var translation = "";
            alert(this.Units.Hours.Values.length+"/"+this.Units.Minutes.Values.length);
            if((this.Units.Minutes.NotationType!=CrontabTimeUnityNotationType.Every) || (this.Units.Hours.NotationType!=CrontabTimeUnityNotationType.Every)) {
                if(this.Units.Hours.Values.length>0 && this.Units.Minutes.Values.length>0) translation="A "+this.Units.Hours.ValuesToString("h")+" pass&eacute;es de "+this.Units.Minutes.ValuesToString()+" minutes";
                else if(this.Units.Minutes.Values.length>0) translation = "Toutes les heures pass&eacute;es de " + this.Units.Minutes.ValuesToString()+" minutes";
                else if(this.Units.Hours.Values.length>0) translation = "Toutes les minutes &agrave; "+ this.Units.Hours.ValuesToString()+" heures";
            }
            else translation = "Toutes les minutes de toutes les heures";
            var daysTranslation="";
            if((this.Units.MonthDays.NotationType!=CrontabTimeUnityNotationType.Every) || (this.Units.WeekDays.NotationType!=CrontabTimeUnityNotationType.Every)) {
                function GetDayString(dayNumber) {switch(parseInt(dayNumber)) {case 0:return "dimanche";case 1:return "lundi";case 2:return "mardi";case 3:return "mercredi";case 4:return "jeudi";case 5:return "vendredi";case 6:return "samedi";}}
                if(this.Units.MonthDays.Values.length>0) daysTranslation = " le " + this.Units.MonthDays.ValuesToString().replace("1,","1er,");
                if(this.Units.WeekDays.Values.length>0) {if(daysTranslation != "") daysTranslation += ",";daysTranslation += " le " + this.Units.WeekDays.ValuesToString(null,GetDayString);}
            }
            else daysTranslation += " chaque jour";
            translation+=daysTranslation;
            if(this.Units.Monthes.NotationType!=CrontabTimeUnityNotationType.Every) {
                function GetMonthString(monthNumber) {switch(parseInt(monthNumber)) {case 1:return "janvier";case 2:return "f&eacute;vrier";case 3:return "mars";case 4:return "avril";case 5:return "mai";case 6:return "juin";case 7:return "juillet";case 8:return "aout";case 9:return "septembre";case 10:return "octobre";case 11:return "novembre";case 12:return "d&eacute;cembre";}}
                if(this.Units.Monthes.Values.length==1) translation += " pendant le mois de " + this.Units.Monthes.ValuesToString(null,GetMonthString);
                else translation+= ", les mois de "+ this.Units.Monthes.ValuesToString(null,GetMonthString);
            }
            else translation += " de chaque mois";
            return translation;
        }
        else return "Unable to translate: not valid crontab expression";
    };
}

