﻿(function ($) {

    function makeExplodable(formDiv) {

        var _transitionSpeed = "fast";
        var _maxChildAge = 17;
        var _expandedFormWidth = 550;
        var _form = $("#" + formDiv);
        var _container = $(".form-container", _form);
        var _dialog = null;

        // Expands the form to show additional options and blacks out the rest of the page.
        function explodeForm(onOpen) {
            if (_dialog != null)
                return;

            _dialog = _container.clone().prependTo("body").addClass("exploded");
            //            .removeClass("hasDatepicker").unbind().removeData("datepicker");
            _dialog.dialog({ modal: true, title: "Booking Options", width: 'auto', close: implodeForm, open: function (event, ui) {

                // HACK: Because the form in this dialog is a clone, the datepickers in it get all screwed up,
                // so we need to manually remove all the datepicker stuff and then re-add it to make it work.
                $(".hasDatepicker", _dialog).each(function () {
                    $(this).removeData("datepicker").unbind().removeClass("hasDatepicker").removeAttr("id");
                });
                $(".date", _dialog).datepicker();

                // Carry over the current number of rooms.
                $("select[name=rooms]", _dialog).val($("select[name=rooms]", _container).val());
                // Carry over the current number of adults.
                $(".adult-count:first select", _dialog).val($("select[name=adults]", _container).val());
                // Hide the simple input fields.
                $(".adult-count-row, .child-count-row", _dialog).slideUp(_transitionSpeed);
                // Make the expanded input fields visible.
                $(".optional-fields", _dialog).slideDown(_transitionSpeed);

                // Event handlers
                $("select[name=rooms]", _dialog).change(roomCountDidChange);
                _dialog.delegate(".people-count-row .child-count select", "change", roomChildCountDidChange);

                $("select[name=rooms]", _dialog).focus();

                if (onOpen)
                    onOpen();
            }
            });
        }

        // Does the opposite of explode form. Disables the blackout, shrinks the form and slides it back into place.
        function implodeForm() {
            // Reset the room and child counts.
            $("select[name=rooms] option:first", _container).attr("selected", true);
            $("select[name=children] option:first", _container).attr("selected", true);

            _dialog.remove();
            _dialog = null;
        }

        // Called when the user selects a new room count.
        // Can happen with an imploded or exploded form.
        function roomCountDidChange(event) {
            var roomCount = parseInt($(this).val());

            if (_dialog != null) {
                updatePeopleCountRows(roomCount);
                updateChildAgeRows(roomCount);
            }
            if (roomCount > 1) {
                explodeForm(function () {
                    updatePeopleCountRows(roomCount);
                    updateChildAgeRows(roomCount);
                });
            }
        }

        // Called when the Children dropdown changes.
        // Can only happen with an imploded form since this field is hidden in the exploded form.
        function childCountDidChange(event) {
            var roomCount = parseInt($("select[name=rooms]", _container).val());
            var childCount = parseInt($("select[name=children]", _container).val());

            if (childCount > 0)
                explodeForm(function () {
                    var room1children = $(".child-count select[name=children-room-1]", _dialog);
                    room1children.val(childCount);
                    updatePeopleCountRows(roomCount);
                    updateChildAgeRows(roomCount);
                });
        }

        // Called when the user changes the number of children for a specific room.
        // Can only happen with an exploded form.
        function roomChildCountDidChange(event) {
            // It's easier to completely rebuild the child age table in this case,
            // so just grab the room count and go.
            var roomCount = parseInt($("select[name=rooms]", _dialog).val());
            updateChildAgeRows(roomCount);
        }

        // Updates the table where people can select how many adults and children can be in a given room.
        // We need to create or remove rows depending on the number of rooms selected.
        function updatePeopleCountRows(roomCount) {
            // Get the existing rows.
            var peopleCountRows = $(".people-count-row", _dialog);
            if (peopleCountRows.length < roomCount) {
                // We need to add more rows.
                var rowsToAdd = roomCount - peopleCountRows.length,
                    roomNumber = peopleCountRows.length + 1,
                    countRow = peopleCountRows.eq(0),
                    countTable = countRow.closest("table");

                for (var i = 0; i < rowsToAdd; i++) {
                    // For each new row, make a clone, set its properties and add it to the table.
                    var newRow = countRow.clone();
                    newRow.find("select option:first-child").attr("selected", true);
                    $(".room-number", newRow).text("Room " + roomNumber);
                    $(".adult-count select", newRow).attr("name", "adults-room-" + roomNumber);
                    $(".child-count select", newRow).attr("name", "children-room-" + roomNumber);
                    countTable.append(newRow);
                    roomNumber++;
                }
            }
            else if (peopleCountRows.length > roomCount) {
                // We have too many rows, so just strip off the unneeded rows from the end.
                for (var i = roomCount, length = peopleCountRows.length; i <= length; i++)
                    peopleCountRows.eq(i).remove();
            }
        }

        // Controls the table where people can input the age of each child in each room.
        // This function specifically ensures that the correct number of rows exists and then
        // calls another helper to manage the columns and dropdowns.
        function updateChildAgeRows(roomCount) {
            // What's the max number of children any of these rooms can have?
            // This will determine the total number of columns.
            var mostChildrenPerRoom = getMostChildrenPerRoom();
            toggleChildrenAges(mostChildrenPerRoom);
            if (mostChildrenPerRoom == 0)
                return;

            // Get the existing rows.
            var childAgeRows = $(".child-age-row", _dialog);

            if (childAgeRows.length < roomCount) {
                // We need to add more rows.
                var rowsToAdd = roomCount - childAgeRows.length,
                    roomNumber = childAgeRows.length + 1,
                    ageRow = childAgeRows.eq(0),
                    ageTable = ageRow.closest("table");

                for (var i = 0; i < rowsToAdd; i++) {
                    // For each row, make a clone, set its properties and append it.
                    var newRow = ageRow.clone();
                    $(".room-number", newRow).text("Room " + roomNumber);
                    ageTable.append(newRow);
                    roomNumber++;
                }
            }
            else if (childAgeRows.length > roomCount) {
                // Too many rows so strip off the end.
                for (var i = roomCount, length = childAgeRows.length; i <= length; i++)
                    childAgeRows.eq(i).remove();
            }

            updateChildAgeColumns();
        }

        // Looks at the number of children that will be in each room and returns the largest one.
        function getMostChildrenPerRoom() {
            var childCounts = $(".child-count select", _dialog);
            var mostChildrenPerRoom = 0;
            for (var room = 0, length = childCounts.length; room < length; room++) {
                var children = parseInt(childCounts.eq(room).val());
                mostChildrenPerRoom = (mostChildrenPerRoom > children ? mostChildrenPerRoom : children);
            }

            return mostChildrenPerRoom;
        }

        // Hides or shows the bottom section of the form with the child ages.
        // If no children are coming, this section doesn't need to be visible.
        function toggleChildrenAges(mostChildren) {
            if (mostChildren == 0)
                $(".children-ages", _dialog).slideUp();
            else
                $(".children-ages", _dialog).slideDown();
        }

        // Goes through each room, looks up the number of children staying in that room and ensures
        // that the correct number of age columns is available.
        function updateChildAgeColumns() {
            // What's the max number of children any of these rooms can have?
            var mostChildrenPerRoom = getMostChildrenPerRoom();
            toggleChildrenAges(mostChildrenPerRoom);
            if (mostChildrenPerRoom == 0)
                return;

            var childAgeTable = $(".child-age-table", _dialog);

            // Make sure we have the right number of columns in the header first.
            var headerRow = childAgeTable.find("tr:first");
            var headerColumns = $("th", headerRow);
            if (headerColumns.length < mostChildrenPerRoom) {
                for (var i = headerColumns.length + 1; i <= mostChildrenPerRoom; i++)
                    $("<th>").text("Child " + i).appendTo(headerRow);
            }
            else if (headerColumns.length > mostChildrenPerRoom) {
                for (var i = mostChildrenPerRoom; i < headerColumns.length; i++)
                    headerColumns.eq(i).remove();
            }

            // Make a dropdown with ages in it that can be cloned for each column.
            var childAgeDropdown = makeChildAgeDropdown(_maxChildAge);

            // Make sure each room row has the right number of children
            var childAgeRows = $(".child-age-row", _dialog);
            for (var room = 0, length = childAgeRows.length; room < length; room++) {
                var row = childAgeRows.eq(room),
                    ageColumns = $(".child-age-column", row),
                    childrenInThisRoom = parseInt($("select[name=children-room-" + (room + 1) + "]", _dialog).val());

                // Do we have enough columns with dropdowns in them?
                if (ageColumns.has("select").length < childrenInThisRoom) {
                    for (var i = 0; i < childrenInThisRoom; i++) {
                        if (i < ageColumns.length) {
                            // The cell already exists.
                            // Only add in a dropdown if we don't have one already
                            if (ageColumns.eq(i).has("select").length == 0)
                                ageColumns.eq(i).append(childAgeDropdown.clone().attr("name", "room-" + (room + 1) + "-childage-" + (i + 1)));
                        }
                        else
                        // The cell does not exist yet.
                        // Append a new cell with a dropdown in it.
                            $("<td>").addClass("child-age-column").appendTo(row).append(childAgeDropdown.clone().attr("name", "room-" + (room + 1) + "-childage-" + (i + 1)));

                    }
                }
                else if (ageColumns.length > childrenInThisRoom) {
                    // We have more columns than there are children, so just trim off the end.
                    for (var i = childrenInThisRoom; i < ageColumns.length; i++)
                        ageColumns.eq(i).find("select").remove();
                }
            }
        }

        // Creates a dropdown pre-filled with the right options.
        function makeChildAgeDropdown(maxYears) {
            var html = "<select><option>-?-</option>";
            for (var i = 1; i <= maxYears; i++) {
                html += "<option>" + i + "</option>";
            }
            html += "</select>";
            return $(html);
        }

        // Once everything is ready, attach our event handlers.
        $(".date", _container).datepicker();
        $("select[name=rooms]", _container).change(roomCountDidChange);
        $("select[name=children]", _container).change(childCountDidChange);
    }

    $(function () {
        makeExplodable("reservation-form");
        makeExplodable("rates-form");
    });
})(jQuery);
