(function () {
    function updateSelect(select, items, selection) {
        select.options.length = 1;
        items.each (function(item) {
            select.options.add(new Option(item.name, item.id));
        });
        selectValue(select, selection);
    }

    function selectValue(select, value) {
        for (var i = 0; i < select.options.length; i++) {
            if (select.options[i].value == value) {
                select.selectedIndex = i;
                return;
            }
        }
    }

    function api(options) {
        options = options || {};
        var getAreaId = options.getAreaId || Prototype.K;
        var areaCompleteEvent = options.areaCompleteEvent || Prototype.K;

        var getZipCode = options.getZipCode || Prototype.K;
        var zipCodeCompleteEvent = options.zipCodeCompleteEvent || Prototype.K;

        var getPrefectureId = options.getPrefectureId || Prototype.K;
        var prefectureCompleteEvent = options.prefectureCompleteEvent || Prototype.K;
        var prefectureCompleteEvent2 = options.prefectureCompleteEvent2 || Prototype.K;

        var getRailwayId = options.getRailwayId || Prototype.K;
        var railwayCompleteEvent = options.railwayCompleteEvent || Prototype.K;

        function request(url, parameters, completeEvent) {
            new Ajax.Request(url, {
                method: 'get',
                parameters: parameters,
                onComplete: function(response) {
                    try {
                        completeEvent(getJson(response));
                    } catch (e) {
                        alert(e);
                    }
                }
            });
        }

        function makeCache(emptyValue) {
            var cache = {};
            cache[''] = emptyValue;
            return cache;
        }

        function getJson(response) {
            return eval('(' + response.responseText + ')');
        }

        var areaCache = makeCache([]);
        function updateArea() {
            var areaId = getAreaId();
            if (areaCache[areaId]) {
                areaCompleteEvent(areaCache[areaId]);
                return;
            }
            request('/api/prefectures', {area_id: areaId}, function(prefectures) {
                areaCache[areaId] = prefectures;
                areaCompleteEvent(prefectures)
            });
        }

        function updateZipCode() {
            var zipCode = getZipCode().replace('-', '');
            request('/api/zip_code', {zip_code: zipCode}, zipCodeCompleteEvent);
        }

        var prefectureCache = makeCache([]);
        function updatePrefecture() {
            var prefectureId = getPrefectureId();
            if (prefectureCache[prefectureId]) {
                prefectureCompleteEvent(prefectureCache[prefectureId]);
                return;
            }
            request('/api/cities', {prefecture_id: prefectureId}, function(cities) {
                prefectureCache[prefectureId] = cities;
                prefectureCompleteEvent(cities);
            });
        }

        var prefecture2Cache = makeCache([]);
        function updatePrefecture2() {
            var prefectureId = getPrefectureId();
            if (prefecture2Cache[prefectureId]) {
                prefectureCompleteEvent2(prefecture2Cache[prefectureId]);
                return;
            }
            request('/api/railways', {prefecture_id: getPrefectureId()}, function(railways) {
                prefecture2Cache[prefectureId] = railways;
                prefectureCompleteEvent2(railways);
            });
        }

        var railwayCache = makeCache([]);
        function updateRailway() {
            var railwayId = getRailwayId();
            if (railwayCache[railwayId]) {
                railwayCompleteEvent(railwayCache[railwayId]);
                return;
            }
            request('/api/stations', {railway_id: railwayId}, function(stations) {
                railwayCache[railwayId] = stations;
                railwayCompleteEvent(stations)
            });
        }

        return {
            updateArea: updateArea,
            updateZipCode: updateZipCode,
            updatePrefecture: updatePrefecture,
            updatePrefecture2: updatePrefecture2,
            updateRailway: updateRailway
        };
    }

    function inputSetup(zipButtonId, zipText1Id, zipText2Id, prefectureSelectId, citySelectId, addressTextId) {
        var zipButton  = $(zipButtonId);
        var zipText1 = $(zipText1Id);
        var zipText2 = $(zipText2Id);
        var prefectureSelect = $(prefectureSelectId);
        var citySelect = $(citySelectId);
        var addressText = $(addressTextId);

        var a = api({
            getZipCode: function() {
                return zipText1.getValue() + zipText2.getValue();
            },
            zipCodeCompleteEvent: function(result) {
                updateSelect(citySelect, result.cities, result.city_id);
                selectValue(prefectureSelect, result.prefecture_id);
                addressText.value = result.address;
            },
            getPrefectureId: function() {
                return prefectureSelect.getValue();
            },
            prefectureCompleteEvent: function(cities) {
                updateSelect(citySelect, cities, '');
            }
        });
        prefectureSelect.observe('change', a.updatePrefecture);
        zipButton.observe('click', a.updateZipCode);
    }

    function companyInputSetup(zipButtonId, zipTextId1, zipTextId2, prefectureSelectId, citySelectId, addressTextId, railwaySelectId, stationSelectId) {
        var zipButton = $(zipButtonId);
        var zipText1 = $(zipTextId1);
        var zipText2 = $(zipTextId2);
        var prefectureSelect = $(prefectureSelectId);
        var citySelect = $(citySelectId);
        var addressText = $(addressTextId);
        var prefectureSelect = $(prefectureSelectId);
        var citySelect = $(citySelectId);
        var addressText = $(addressTextId);
        var railwaySelect = $(railwaySelectId);
        var stationSelect = $(stationSelectId);

        var a = api({
            getZipCode: function() {
                return zipText1.getValue() + zipText2.getValue();
            },
            zipCodeCompleteEvent: function(result) {
                updateSelect(citySelect, result.cities, result.city_id);
                selectValue(prefectureSelect, result.prefecture_id);
                addressText.value = result.address;
                updateSelect(railwaySelect, result.railways, '');
                updateSelect(stationSelect, [], '');
            },
            getPrefectureId: function() {
                return prefectureSelect.getValue();
            },
            prefectureCompleteEvent: function(cities) {
                updateSelect(citySelect, cities, '');
            },
            prefectureCompleteEvent2: function(railways) {
                updateSelect(railwaySelect, railways, '');
            },
            getRailwayId: function() {
                return railwaySelect.getValue();
            },
            railwayCompleteEvent: function(stations) {
                updateSelect(stationSelect, stations, '');
            }
        });
        zipButton.observe('click', a.updateZipCode);
        prefectureSelect.observe('change', a.updatePrefecture);
        prefectureSelect.observe('change', a.updatePrefecture2);
        railwaySelect.observe('change', a.updateRailway);
    }

    function estateInputSetup(zipButtonId, zipTextId, prefectureSelectId, citySelectId, addressTextId, railwaySelectId, stationSelectId) {
        var zipButton = $(zipButtonId);
        var zipText = $(zipTextId);
        var prefectureSelect = $(prefectureSelectId);
        var citySelect = $(citySelectId);
        var addressText = $(addressTextId);
        var prefectureSelect = $(prefectureSelectId);
        var citySelect = $(citySelectId);
        var addressText = $(addressTextId);
        var railwaySelect = $(railwaySelectId);
        var stationSelect = $(stationSelectId);

        var a = api({
            getZipCode: function() {
                return zipText.getValue();
            },
            zipCodeCompleteEvent: function(result) {
                updateSelect(citySelect, result.cities, result.city_id);
                selectValue(prefectureSelect, result.prefecture_id);
                addressText.value = result.address;
                updateSelect(railwaySelect, result.railways, '');
            },
            getPrefectureId: function() {
                return prefectureSelect.getValue();
            },
            prefectureCompleteEvent: function(cities) {
                updateSelect(citySelect, cities, '');
            },
            getRailwayId: function() {
                return railwaySelect.getValue();
            },
            railwayCompleteEvent: function(stations) {
                updateSelect(stationSelect, stations, '');
            }
        });
        zipButton.observe('click', a.updateZipCode);
        prefectureSelect.observe('change', a.updatePrefecture);
        prefectureSelect.observe('change', a.updatePrefecture2);
        railwaySelect.observe('change', a.updateRailway);
    }

    function searchSetup(areaSelectId, prefectureSelectId, citySelectId, railwaySelectId, stationSelectId) {
        var areaSelect = $(areaSelectId);
        var prefectureSelect = $(prefectureSelectId);
        var citySelect = $(citySelectId);
        var railwaySelect = $(railwaySelectId);
        var stationSelect = $(stationSelectId);

        var a = api({
            getAreaId: function() {
                return areaSelect.getValue();
            },
            areaCompleteEvent: function(prefectures) {
                updateSelect(prefectureSelect, prefectures, '');
                updateSelect(citySelect, [], '');
                updateSelect(railwaySelect, [], '');
                updateSelect(stationSelect, [], '');
            },
            getPrefectureId: function() {
                return prefectureSelect.getValue();
            },
            prefectureCompleteEvent: function(cities) {
                updateSelect(citySelect, cities, '');
            },
            prefectureCompleteEvent2: function(railways) {
                updateSelect(railwaySelect, railways, '');
                updateSelect(stationSelect, [], '');
            },
            getRailwayId: function() {
                return railwaySelect.getValue();
            },
            railwayCompleteEvent: function(stations) {
                updateSelect(stationSelect, stations, '');
            }
        });

        areaSelect.observe('change', a.updateArea);
        prefectureSelect.observe('change', a.updatePrefecture);
        prefectureSelect.observe('change', a.updatePrefecture2);
        railwaySelect.observe('change', a.updateRailway);
    }

    window.inputSetup = inputSetup;
    window.searchSetup = searchSetup;
    window.companyInputSetup = companyInputSetup;
})();
