﻿/// <reference path="extensions.js" />





// crud
$.fn.crudGrid = function (options) {

    var settings = $.extend({
        //IsEditable:true,
        isViewable: true
    }, options);

    var container = $(this).addClass("crud-grid");

    var generateCrudGrid = function (gridData) {

        return container.each(function () {


            $(this).loading();

            var config;


            var processGridData = function (data) {


                config = $.extend(true, JSON.parseWithDate(data), settings);
                //debugger;
                container.removeLoading();

                container.empty();
                var table = $('<table cellpadding="0" cellspacing="0" border="0"/>')
                if (config.data.length > 0) {
                    table.appendTo(container);
                }
                else {
                    if (config.noResults) {
                        container.append(config.noResults);
                    }
                    else {
                        container.append($('<p></p>').text("No " + config.EntityPluralName.toLowerCase() + " have been added yet"))
                    }
                }
                var thead = $('<thead/>').appendTo(table);
                var thead_tr = $('<tr/>').appendTo(thead);
                var tbody = $('<tbody/>').appendTo(table);



                //check if gridfields have been defined
                if (config.GridFields.length == 0) {
                    $.each(config.Fields, function (fieldName, field) {
                        if (fieldName != config.PrimaryKey) {
                            config.GridFields.push(fieldName)
                        }
                    })
                }

                var standardFormatter = function (value) {
                    if (value == null) { return "-" }
                    if ($.is.Date(value)) {
                        return $.datepicker.formatDate("dd M yy", value)
                    }
                    return value
                }


                //setup some field defaults

                var fields = {};
                var detailFields = {};
                $.each(config.Fields, function (fieldName, field) {
                    if (fieldName != config.PrimaryKey) {
                        fields[fieldName] = field;
                    }

                });

                $.each(fields, function (fieldName, field) {

                    if (field.formatter == null) {
                        //                        if (field.CrudType == "multiple-lookup") {
                        //                            field.formatter = function(value, item) {
                        //                                var out = "";
                        //                                $.each(value, function(index, subitem) {
                        //                                    out += (index > 0 ? ", " : "") + subitem[field.LookupDisplayField]
                        //                                })
                        //                                return out;
                        //                            }
                        //                        }
                        //else { 
                        field.formatter = standardFormatter;
                        //}
                    }
                    if (!field.Label) {
                        field.Label = $.humanizeCamelCase(fieldName)
                    }
                    if (!field.dontDetail) { detailFields[fieldName] = field }
                })

                // setup thead
                $.each(config.GridFields, function (gridFieldIndex, gridFieldName) {
                    var field = config.Fields[gridFieldName] //$.getValueOrDefault(config.Fields,gridFieldName, {})
                    $('<th/>').addClass("cg-" + gridFieldName).text($.getValueOrDefault(field, ["GridLabel", "Label"], gridFieldName)).appendTo(thead_tr)
                })
                if (config.isViewable || config.IsEditable || config.CanDelete) { thead_tr.append('<th class="actions"></th>') }




                // View Item

                var viewItem = function (item, isNew) {

                    // Show Details

                    //                    $.createIfNotExists(item, "formElements")
                    //                    $.createIfNotExists(item, "formDetails")
                    //                    $.createIfNotExists(item, "formInputs")
                    var crudDetail = $('<div class="crud-details"/>')
                    var formElements = crudDetail.data().formElements = {}
                    var formDetails = crudDetail.data().formDetails = {}
                    var formInputs = crudDetail.data().formInputs = {}


                    $.each(detailFields, function (fieldName, field) {


                        var detail = $('<div class="text" />')
                        if (field.displayFunction) {
                            field.displayFunction(detail, item[fieldName], item)
                        }
                        else if (field.CrudType == "textarea") {
                            detail.append($("<pre/>").addClass("format no-margin").text(item[fieldName]))
                        }
                        else if (field.CrudType == "multiple-lookup") {

                            detail = $('<div class="multiple-text"/>')
                            var values = item[fieldName]
                            for (var i = 0; i < values.length; i++) {
                                $('<div class="text"/>').text(values[i][field.LookupDisplayField]).appendTo(detail)
                            }

                        }
                        else if (field.CrudType == "multiple-dates") {
                            detail = $('<div class="multiple-text"/>');
                            var values = item[fieldName];
                            for (var i = 0; i < values.length; i++) {
                                var value = $.datepicker.formatDate("dd M yy", values[i][field.LookupDisplayField])
                                $('<div class="text"/>').text(value).appendTo(detail)
                            }
                        }
                        else {
                            detail.text(field.formatter(item[fieldName], item))
                        }

                        crudDetail.append(
                            formElements[fieldName] = $('<div class="formElement"/>').addClass("crud-detail-" + fieldName).append(
                                $('<label/>').attr("for", "crud-" + fieldName).text(field.Label)
                            ).append(
                                formDetails[fieldName] = $('<div class="detail"/>').append(detail)
                            )
                        )
                        if (field.CrudType == "rating") {
                            formDetails[fieldName].starWidget();
                        }
                    })

                    var editMessage = $('<div class="message"/>')

                    var edit = function () {

                        //reconfigure the buttons
                        crudDetail.dialog("option", "buttons", {
                            "Save Changes": function () {

                                //Save changes

                                var screen = $.screen();

                                editMessage.removeClass("error").addClass("saving").text("Saving...")

                                $.each(detailFields, function (fieldName, field) {
                                    //debugger;
                                    if (field.IsEditable) { item[fieldName] = formInputs[fieldName].getValue(); }
                                })

                                // crudDetail.loading();

                                $.post(config.UpdateUrl, { Data: JSON.stringify(item) }, function (response) {


                                    if (response.IsValid == true) {
                                        screen.remove();
                                        crudDetail.dialog("close");
                                        generateCrudGrid();
                                        if (config.onUpdate) { config.onUpdate(); }
                                    }

                                    else {
                                        dialog.find("span.error").remove();
                                        dialog.find(".formElement").removeClass("invalid");

                                        var ruleViolations = response.RuleViolations
                                        if (ruleViolations) {
                                            for (var i in ruleViolations) {
                                                formElements[ruleViolations[i].PropertyName].addClass("invalid").find(".detail").append($("<span/>").addClass("error").text(ruleViolations[i].ErrorMessage))
                                            }
                                        }

                                        screen.remove()
                                        editMessage.removeClass("saving").addClass("error").text("Oops. " + (response.RuleViolations == null ? "Server Error, please try again" : "Please check the errors above"));


                                    }

                                    //console.log(response);
                                })
                            }
                        })

                        var dialog = crudDetail.dialog("widget");
                        dialog.find(".ui-dialog-buttonpane").append(editMessage);

                        $.each(detailFields, function (fieldName, field) {
                            //debugger;
                            if (field.IsEditable) {

                                var inputCode = null;

                                switch (field.CrudType) {
                                    case "textarea":
                                        inputCode = $('<textarea></textarea>');
                                        break;
                                    case "select":
                                        inputCode = $('<select></select>');
                                        break;
                                    default:
                                        inputCode = $('<input type="text" style="height:15px;"/>');
                                        break;
                                }

                                var input = formInputs[fieldName] = $(inputCode).appendTo(formDetails[fieldName].empty())
                                if (field.CrudType == "multiple-dates") {
                                    input.multipleInput({ displayField: field.LookupDisplayField, type: "date" });
                                }
                                else if (field.CrudType.toLowerCase().indexOf("date") > 0) {
                                    input.dateWidget();
                                }
                                else if (field.CrudType == "multiple-lookup") {
                                    input.multipleInput({ displayField: field.LookupDisplayField, lookupOptions: field.LookupOptions });
                                }
                                else if (field.CrudType == "rating") {
                                    input.starWidget();
                                    input.remove();
                                }
                                else if (field.CrudType == "select") {
                                    var values = new Array();

                                    $.each(field.LookupOptions, function (index) {
                                        values[index] = this.Value;
                                    });

                                    input = formInputs[fieldName] = input.superInput({ source: values });
                                    input.height(15);
                                }

                                if (field.initInput) {
                                    field.initInput(input, item, fieldName);
                                }
                                input.setValue(item[fieldName] == null ? "" : item[fieldName])
                            }
                        })

                        crudDetail.dialog("open");
                        setTimeout(function () { crudDetail.find("input,select").eq(0).focus(); }, 500);
                        if (config.onEdit) { config.onEdit(crudDetail) }

                        $(".crud-details").find(".spinner").width(50);

                        if (crudDetail[0].scrollHeight > crudDetail.outerHeight()) {
                            editMessage.removeClass("saving").addClass("error").text("Please scroll down to complete")
                        }
                    }


                    var viewButtons = { "Edit": function () { crudDetail.dialog("destroy"); viewItem(item, true); } };

                    if (!config.IsEditable) {
                        viewButtons = { "Close": function () { crudDetail.dialog("close"); } }
                    }

                    var dialogOptions = { title: config.EntityName + " Details", buttons: viewButtons, height: "auto" }

                    dialogOptions.autoOpen = false;
                    dialogOptions.width = 705;

                    crudDetail.customDialog(dialogOptions).dialog("widget").addClass("crud-dialog");

                    if (isNew) { setTimeout(edit, 500) }
                    else {
                        if (config.onItemViewed) { config.onItemViewed(crudDetail) }
                        crudDetail.dialog("open")
                    }

                    return false;
                }


                var rowEvenOdd = function () {
                    tbody.find("tr").each(function (rowIndex) {
                        $(this).addClass(rowIndex % 2 == 0 ? "odd" : "even")
                        $(this).removeClass(rowIndex % 2 == 0 ? "even" : "odd")
                    });
                };

                // set up data rows
                $.each(config.data, function (rowIndex, item) {

                    var tr = $('<tr/>').appendTo(tbody);



                    if (config.rowAction) {
                        tr.addClass("clickable").attr("title", config.rowAction.title).click(function () {
                            config.rowAction.action(item, tr);
                        })
                    }

                    else if (config.isViewable) {
                        tr.addClass("clickable").attr("title", "Click to view details").click(function () {
                            viewItem(item);
                        })
                    }
                    else if (config.IsEditable) {
                        tr.addClass("clickable").attr("title", "Click to edit details").click(function () {
                            viewItem(item, true);
                        })
                    }

                    $.each(config.GridFields, function (gridFieldIndex, gridFieldName) {

                        var field = config.Fields[gridFieldName]//$.getValueOrDefault(config.Fields, gridFieldName, {})
                        var td = $('<td/>').addClass("cg-" + gridFieldName).appendTo(tr)
                        var value = item[gridFieldName];
                        //debugger;
                        var displayFunction = $.getValueOrDefault(field, ["gridDisplayFunction", "displayFunction"], null)
                        if (displayFunction) {
                            displayFunction(td, value, item)
                        }
                        else {
                            td.text($.getValueOrDefault(field, ["gridFormatter", "formatter"])(value, item));
                        }
                        if (field.CrudType == "rating") {
                            td.starWidget()
                        }
                    })

                    if (config.isViewable || config.IsEditable || config.CanDelete) {
                        var actionCell = $('<td class="actions"/>').appendTo(tr);

                        if (config.isViewable) {
                            var viewButton = $('<a href="#" class="view" title="View Details">&nbsp;</a>').appendTo(actionCell).click(function () { return viewItem(item); });
                        }

                        if (config.IsEditable) {
                            var editButton = $('<a href="#" class="edit" title="Edit">&nbsp;</a>').appendTo(actionCell).click(function () { return viewItem(item, true); });
                        }

                        if (config.CanDelete) {
                            var deleteButton = $('<a href="#" class="delete" title="Delete">&nbsp;</a>').appendTo(actionCell).click(function () {
                                // Delete confirmation
                                var dialog;
                                dialog = $.confirm("Are you sure you want to delete this item?", function () {
                                    //Delete Confirmed
                                    tr.addClass("deleting").removeClass("clickable").unbind().attr("title", "Deleting...");
                                    //container.loading();
                                    dialog.dialog("close");
                                    $.post(config.DeleteUrl, { id: item[config.PrimaryKey] }, function (data) {
                                        generateCrudGrid();

                                        if (config.onDelete) { config.onDelete() }
                                    }, "text")
                                }, null, { width: 400 });

                                return false;
                            })
                        }
                    }


                });

                rowEvenOdd();

                if (config.CanCreate) {
                    var addItemButton = $("<button/>").button({
                        label: config.addButtonText ? config.addButtonText : ("Add " + config.EntityName)

                    }).appendTo(container).click(function () {
                        var newObj = $.extend({}, config.NewItem)
                        viewItem(newObj, true)
                    })
                }

            }


            if (gridData) { processGridData(gridData) }
            else {
                $.get(settings.url + "?t=" + new Date().getTime(), settings.requestData, processGridData, "text")
            }

        })
    }
    //return 
    generateCrudGrid();
    return $(this)
}
