var ajax = (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
        };
    }
    return {
        api: api,
        updateSelect: updateSelect,
        selectValue: selectValue
    };
})();
