var DataColumn = new Class({
    name: "",
    type: "String",
    data: [],
    sortedIndices: [],

    initialize: function(name, data) {
        this.name = name;
        if (data != null) {
            this.data = data;
            this.determineDataType();
        }
    },
    getName: function() {
        return this.name;
    },
    setName: function(name) {
        this.name = name;
    },
    getType: function() {
        return this.type;
    },
    setType: function(type) {
        this.type = type;
    },
    getValue: function(index) {
        return this.data[index];
    },
    getAllValues: function() {
        return this.data;
    },
    setValue: function(index, value) {
        this.data[index] = value;
    },
    getCount: function() {
        return this.data.length;
    },
    sort: function() {
        for (var i = 0; i < this.data.length; i++) {
            this.sortedIndices.push(i);
        }

        for (var i = 0; i < this.sortedIndices.length - 1; i++) {
            var lowestIndex = i + 1;
            for (var j = i + 2; j < this.sortedIndices.length; j++) {
                if (this.data[this.sortedIndices[j]] < this.data[this.sortedIndices[lowestIndex]]) {
                    lowestIndex = j;
                }
            }
            if (this.data[this.sortedIndices[lowestIndex]] < this.data[this.sortedIndices[i]]) {
                var temp = this.sortedIndices[lowestIndex];
                this.sortedIndices[lowestIndex] = this.sortedIndices[i];
                this.sortedIndices[i] = temp;
            }
        }
    },
    attemptToChangeTypeTo: function(newType, stopAtFirstCatch) {
        if (this.type == newType)
            return true;

        var conversionFunction;
        var validationFunction;
        if (newType == "String") {
            conversionFunction = function(value) {return String(value);}
            validationFunction = function(value, result) {return true;};
        }
        else if (newType == "Integer") {
            if (this.type == "String")
                conversionFunction = function(value) {return parseInt(value);};
            if (this.type == "Decimal")
                conversionFunction = function(value) {return Math.floor(value);};
            if (this.type == "Boolean")
                conversionFunction = function(value) {return (value == "false" || value == 0) ? 0 : 1;};
            validationFunction = function(value, result) {return (value == result || value == "true" && result == 1 || value == "false" && result == 0)};
        }
        else if (newType == "Decimal") {
            if (this.type == "String")
                conversionFunction = function(value) {return parseFloat(value);};
            if (this.type == "Integer")
                conversionFunction = function(value) {return value;};
            if (this.type == "Boolean")
                conversionFunction = function(value) {return (value ? 1.0 : 0.0);};
            validationFunction = function(value, result) {return (value == result || value == "true" && result == 1.0 || value == "false" && result == 0.0)};
        }
        else if (newType == "Boolean") {
            if (this.type == "String")
                conversionFunction = function(value) {return (value == "true" || value == 1)};
            if (this.type == "Integer")
                conversionFunction = function(value) {return value ? true : false;};
            if (this.type == "Decimal")
                conversionFunction = function(value) {return value ? true : false;};
            validationFunction = function(value, result) {return (value == result || (value == "true" || value == 1) && result == true || (value == "false" || value == 0) && result == false)};
        }

        var errors = this.findInvalidRows(conversionFunction, validationFunction, stopAtFirstCatch);
        console.log(JSON.stringify(errors));
        if (errors.length == 0) {
            for (var i = 0; i < this.getCount(); i++)
                this.data[i] = conversionFunction(this.data[i]);
            return true;
        }
        else
            return false

    },
    determineDataType: function() {
        if (this.attemptToChangeTypeTo("Boolean", true))
            this.type = "Boolean";
        else if (this.attemptToChangeTypeTo("Integer", true))
            this.type = "Integer";
        else if (this.attemptToChangeTypeTo("Decimal", true))
            this.type = "Decimal";
        else if (this.attemptToChangeTypeTo("String", true))
            this.type = "String";
        else
            this.type = null;
    },
    findMinimumColumnValue: function() {
        return this.data[this.sortedIndices[this.sortedIndices.length - 1]];
    },
    findInvalidRows: function(conversionFunction, validationFunction, stopAtFirstCatch) {
        var errors = [];
        for (var i = 0; i < this.getCount(); i++) {
            try {
                var originalValue = this.data[i];
                var newValue = conversionFunction(originalValue);
                if (!validationFunction(originalValue, newValue)) {
                    errors.push({error: {index: i, value: this.data[i]}, details: "Converted value doesn't match"});
                    if (stopAtFirstCatch)
                        return errors;
                }
            }
            catch(exception) {
                errors.push({error: {index: i, value: this.data[i]}, details: exception});
                if (stopAtFirstCatch)
                    return errors;
            }
        }
        return errors;
    }
});