 
 {Primitive} = require "./primitive"
 {Barebones} = require "./skeleton"
+
+# A base class for all the validation contexts. Basically the conext
+# encapsulates the necessary internal details as well as provides a
+# set of validators to be used. So in order to create custom ones, you
+# will need to create a descendant of this class and set is as context.
+# The context setting happens on the servies level with the directive.
+module.exports.Context = class Context extends Primitive
+
+    # Create a new instance of the validation context with the given
+    # value set as the subject for validation. Each validator will
+    # refer to this value to perform their validation logic on it.
+    # If the message arg is passed in then it will be used by force.
+    constructor: (@value, @message) ->
+
+    # Chain in a new validator to the context. Validator is a method
+    # that will be called within this context that should look up the
+    # value and see if it fits the validator logic and report either
+    # an error, via standard async callback or pass on to the next one.
+    chain: (validator) ->
+        noFunction = "a #{validator} is not a function"
+        wrongParams = "a validator should have 1 argument"
+        assert _.isFunction(validator), noFunction
+        assert validator.length is 1, wrongParams
+        @emit "chain", validator, @validators
+        (@validators ?= []).push validator
+
+    # Run the entire stack of chained validators. Once done, callback
+    # will be called with an error parameter passed in. If any of the
+    # validators in the chain has failed, then this parameter will have
+    # an error object set in with an appropriate message about mistake.
+    run: (callback) ->
+        validators = @validators ?= []
+        invalid = "inconsistent validators"
+        assert _.isArray validators, invalid
+        async.series validators, (error) =>
+            failed = _.isObject error
+            custom = _.isString @message
+            matches = failed and custom
+            error.message = @message if matches
+            @emit "run", error
+            callback error
 
 # This is an ABC service intended to be used only as a compund. It
 # provides a complete validation solution for the framework. The

        transformed =  _.map _.values(vcontexts), transformer
        transformed = _.object _.keys(vcontexts), transformed
        async.parallel transformed, (error, results) =>
            assert not error, "internval valdation error"
            errors = _.any _.values(results), _.isObject
            hasRender = _.isFunction @renderValidation
            assert hasRender, "no method to render validation"
            params = [results, request, response, continuation]
            return @renderValidation params... if errors
            return continuation.bind(this)()

    # Create a validation context for the parameter designated by
    # the `name` and add it to the current request. If the `message`

        created = new context value, message
        vcontexts[name] = created; created

    # Create a validation context for the parameter designated by
    # the `name` and add it to the supplied storage. If the `message`
    # is supplied then it will be forced as an error messages. Use
    # this method to automatically obtain contex for the parameter.
    value: (storage, name, message) ->
        context = @constructor.validationContext?()
        context = Context unless _.isObject context
        assert storage; value = storage[name]
        vcontexts = (storage.vcontexts ?= {})
        return obtain if obtain = vcontexts[name]
        created = new context value, message
        vcontexts[name] = created; created
