function Action(owner, name, args, label) {
    this.owner = owner
    this.name = name
    this.label = (label || name).humanize().capitalize()
    this.node = document.createElement("div")
    this.argval = []
    this.fn = {}

    var col = 0
    for (var i in args)
        if (typeof (args[i]) == "function") {
            this.fn[i] = args[i]
            delete args[i]
        } else
        create_node("label", i.humanize().capitalize() + ": ", {
            class: "Col" + col++
        }, this.node)

    create_node("br", "", {}, this.node)
    col = 0
    for (var i in args) {
        if (typeof(args[i][0]) == "number" || args[i][0] instanceof Number)
            this.create_numerical_param(i, args[i], col++)
        if (typeof(args[i][0]) == "boolean")
            this.create_boolean_param(i, args[i], col++)
        if (typeof(args[i]) == "function")
            this.argval.push(args[i])
    }
    this.button = create_node("button", this.label, {
        class: "Col2"
    }, this.node)
    this.button.addEventListener("click", (function(that) {
        return function() {
            for (var i in that.fn)
                that.fn[i]()
            var curve = that.owner.get_data_source()
            var res = []
            var values = that.values()
            if (curve[that.name])
                res = curve[that.name].apply(curve, that.values())
            
            that.owner.cast(that.name, res)
        }
    })(this))

}
Action.prototype.add_listeners = function (arg, pos) {
    for (var ev in arg.listeners)
        this.argval[pos].addEventListener(ev, arg.listeners[ev] )
}

Action.prototype.create_numerical_param = function(i, arg, pos) {
    var config = {
        id: this.name.underscore() + "_action_param_" + i + "_" + this.owner.title.underscore(),
        type: "number",
        class: "Col" + pos,
        value: arg[0]
    }
    var step = arg[1]
    if (arg[2])
        config.min = arg[2]
    if (arg[3])
        config.max = arg[3]
    this.argval.push(create_node("input", "", config, this.node))
    if (arg.listeners)
        this.add_listeners(arg, pos)
}

Action.prototype.create_boolean_param = function(i, arg, pos) {
    var config = {
        id: this.name.underscore() + "_action_param_" + i + "_" + this.owner.title.underscore(),
        type: "checkbox",
        class: "Checkbox Col" + pos,
        value: arg[0]
    }

    this.argval.push(create_node("input", "", config, this.node))
    if (arg.listeners)
        this.add_listeners(arg, pos)
}


Action.prototype.values = function() {
    var val = []
    for (var i = 0; i < this.argval.length; i++) {
        if (this.argval[i].type) {
            if (this.argval[i].type == "number")
                val.push(Number(this.argval[i].value))
            else if (this.argval[i].type == "checkbox")
                val.push(this.argval[i].checked)
        } else
        if (typeof(this.argval[i]) == "function")
            val.push(this.argval[i]())
    }

    return val
}

Action.prototype.dom = function() {
    return this.node
}