/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 *           General verification functions
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */


/**
 * Verifies that object specified isn't null or undefined.
 *
 * @param object object to check
 * @param message error message to display in case of verification failure
 * @throws Error if object specified is null or undefined
 */
function verifyNotNullOrUndefined ( object, message ) {
    
    if ( arguments.length != 2 ) {
        error( "verifyNotNullOrUndefined(): there should be two arguments\n" +
               "received [" + arguments.length + "] instead" );
    }

    if ( isNullOrUndefined( object )) {
        error ( "verifyNotNullOrUndefined(): object is null or undefined\n" +
                "The message is [" + message + "]" );
    }
    
}


/**
 * Verifies that object specified is of the type specified.
 *
 * @param object  object to check
 * @param type    "typeof" expected value
 * @param message error message to display in case of verification failure
 * @throws Error  if object specified is null or indefined or it's "typeof"
 *                returns value different from "type"
 */
function verifyType ( object, type, message ) {
    if ( arguments.length != 3 ) {
      error( "verifyType(): there should be three arguments\n" +
             "received [" + arguments.length + "] instead" );
    }
	
    verifyNotNullOrUndefined( object, message );
    
    if ( ! ( typeof object == type )) {
        error( "verifyType(): type of [" + object + "] is " +
               "[" + ( typeof object ) + "] instead of [" + type + "]\n" +
               "The message is [" + message + "]" );
    }
}


/**
 * Verifies that condition specified is *true*.
 *
 * @param condition boolean condition to check
 * @param message   error message to display in case of verification failure
 * @throws Error    if condition specified is false
 */
function verifyTrue ( condition, message ) {

    verifyType( condition, "boolean", "verifyTrue(): condition" );
    verifyType( message,   "string",  "verifyTrue(): message" );

    if ( ! condition ) {
        error( "The condition specified is *false* !\n" +
               "The message is [" + message + "]" );
    }
}


/**
 * Verifies that condition specified is *false*.
 *
 * @param condition boolean condition to check
 * @param message   error message to display in case of verification failure
 * @throws Error    if condition specified is true
 */
function verifyFalse ( condition, message ) {

    verifyType( condition, "boolean", "verifyFalse(): condition" );
    verifyType( message,   "string",  "verifyFalse(): message" );

    if ( condition ) {
        error( "The condition specified is *true* !\n" +
               "The message is [" + message + "]" );
    }
}


/**
 * Verifies that string specified is identical to the value specified
 * (case-insensitive).
 *
 * @param string  string to check
 * @param value   value to compare with
 * @param message error message to display in case of verification failure
 * @throws Error  if string specified differs from the value specified (case-insensitive)
 */
function verifyString ( string, value, message ) {

    verifyType( string,  "string", "verifyString(): string" );
    verifyType( value,   "string", "verifyString(): value" );
    verifyType( message, "string", "verifyString(): message" );

    if ( string.toLowerCase() != value.toLowerCase()) {
        error( "verifyString(): [" + string + "] != [" + value + "] (case-insensitive)\n" +
               "The message is [" + message + "]" );
    }
}


/**
 * Verifies that node specified has a required name.
 *
 * @param node     Node to check
 * @param nodeName name that Node should have
 * @param message error message to display in case of verification failure
 * @throws Error  if node.nodeName differs from nodeName (case-insensitive)
 */
function verifyNodeName ( node, nodeName, message ) {

    verifyType( node,     "object", "verifyNodeName(): node:     [" + message + "]" );
    verifyType( nodeName, "string", "verifyNodeName(): nodeName: [" + message + "]" );
    verifyType( message,  "string", "verifyNodeName(): message:  [" + message + "]" );

    if ( node.nodeName.toLowerCase() != nodeName.toLowerCase()) {
        error( "Node.nodeName = [" + node.nodeName + "] instead of " +
               "[" + nodeName + "] (case-insensitive)\n" +
               "The message is [" + message + "]" );
    }
}


/**
 * Verifies type of the <input node specified.
 *
 * @param  inputNode Node (with "input" nodeName) to check
 * @param  nodeType  node type to check against
 * @param  message error message to display in case of verification failure
 * @throws Error if node specified has node.nodeName different from "input" or
 *               node.type differs from nodeType (case-insensitive)
 */
function verifyInputType ( inputNode, nodeType, message ) {

    verifyType( inputNode, "object", "verifyInputType(): inputNode: [" + message + "]" );
    verifyType( nodeType,  "string", "verifyInputType(): nodeType:  [" + message + "]" );
    verifyType( message,   "string", "verifyInputType(): message:   [" + message + "]" );

    verifyNodeName( inputNode, "input", message );

    if ( inputNode.type.toLowerCase() != nodeType.toLowerCase()) {
        error( "Node.type = [" + inputNode.type + "] " +
               "instead of [" + nodeType + "] (case-insensitive)\n" +
               "The message is [" + message + "]" );
    }
}
