/*
Gizmo(QP) Web Framework - http://gizmojo.org/
------------------------------------------------------------------------------
Copyright (C) 2007 Mario Ruggier
Licensed under the Open Software License version 3.0
------------------------------------------------------------------------------
$Id: spec.js 964 2008-03-17 14:03:29Z mario $ 
*/

// ---------------------------------------------------------------------------

function Spec() {}
Spec.prototype.mer = 'error';
Spec.prototype.submer = null; // bubbled sub error message, from sub-specs
Spec.prototype.mok = 'ok';
Spec.prototype.get_message = function (ok) { 
    return ok ? this.mok : this.submer ? this.mer+this.submer : this.mer;
}
Spec.prototype.test = function () { 
    throw('NotImplementedError: spec.test()'); 
};

// ---------------------------------------------------------------------------

function Both(specs, mer, mok) {
    this.specs = specs;
    this.mer = mer;
    this.mok = mok;
}
Both.prototype = new Spec;
Both.prototype.test = function (value) { 
    for(var i=0; i<this.specs.length; i++) {
        if (!this.specs[i].test(value)) {
            if (this.specs[i].mer) {
                this.submer = this.specs[i].mer;
            }
            else {
                this.submer = null;
            }
            return false;
        }
    }
    return true; 
};

function Either(specs, mer, mok) {
    this.specs = specs;
    this.mer = mer;
    this.mok = mok;
}
Either.prototype = new Spec;
Either.prototype.test = function (value) { 
    for(var i=0; i<this.specs.length; i++) {
        if (this.specs[i].test(value)) {
            this.submer = null;
            return true;
        }
        else {
            this.submer = this.specs[i].mer;
        }
    }
    return false;
};

function Pattern(pattern, mer, mok) {
    this.pattern = pattern;
    this.mer = mer;
    this.mok = mok;
}
Pattern.prototype = new Spec;
Pattern.prototype.test = function (value) { 
    return this.pattern.test(value);
};

function Length(min, max, mer, mok) {
    this.min = min;
    this.max = max; // max may be null
    this.mer = mer;
    this.mok = mok;
}
Length.prototype = new Spec;
Length.prototype.test = function (value) { 
    if (value.length < this.min) { return false; }
    if (this.max!=null) {
        if (value.length > this.max) { return false; }
    }
    return true;
};


// ---------------------------------------------------------------------------
// Specs below assume Gizmo Widgets


/* EqualWidget (assumes Gizmo context):
   - checks this value with that of named widget
   - sets both ok if equal, or both not ok if not equal 
*/
function EqualWidget(name, mer, mok) {
    this.equaled_name = name;
    this.mer = mer;
    this.mok = mok;
}
EqualWidget.prototype = new Spec;
EqualWidget.prototype.test = function (value) { 
    var equaled_widget = eval(this.equaled_name);
    return equaled_widget.set_ok(equaled_widget.get_value()==value);
};


/* ShadowWidget (assumes Gizmo context): 
   - calls named widget's test() (via get_status())
   - updates named widget's status
   - sets own status to same as named widget's 
*/
function ShadowWidget(name, mer, mok) {
    this.shadowed_name = name;
    this.mer = mer;
    this.mok = mok;
}
ShadowWidget.prototype = new Spec;
ShadowWidget.prototype.test = function (value) { 
    var shadowed_widget = eval(this.shadowed_name);
    shadowed_widget.set_status(shadowed_widget.get_status());
    return shadowed_widget.is_ok();
};


// ---------------------------------------------------------------------------

