 /**
 * 收藏夹数据模块
 * @author  zhulin
 * @date 2014-4-11
 * 包括以下逻辑：
 *     对收藏项目数据的请求、本地存储、增删改查；
 *     降价提醒的数据本地增删改；网络同步和具体的交互在depricedReminder.js中
 */
define(function (require, exports, module) {


    var md5 = require('./code.js').md5;
    var msg = require('./msg.js');

    var data = module.exports;

    // ie67的时候，替换base64图片为默认图片
    var isIE67 = false;

    if ($.browser.msie && ($.browser.version === '7.0' || $.browser.version === '6.0')) {
        isIE67 = true;
    }

    var DEFAULT_ITEM_IMAGE = 'http://shared.ydstatic.com/gouwuex/images/extension_2_3/default-img.png';

    function replaceBase64 (item) {
        if (item.img.slice(0, 4) === 'http') return;
        item.img = DEFAULT_ITEM_IMAGE;
    }

    // -------------------------------------------------------------------------
    // 配置 start
    var URL_BASE = 'http://zhushou.huihui.cn/api/';
    var DEFAULT_INIT_DATA_COUNTS = 5; // 首次加载默认的加载数目
    var DEFAULT_PAGE_COUNTS = 20; // 每页的条目数目

    // 本地数据存储
    data.list = [];
    data.pricelowlist = [];
    data.promotionlits = [];

    data.allsize = undefined;  // 服务端所有收藏的数目
    data.depricedsize = undefined; // 记录derpiced的项目数目
    data.promotionsize = undefined; // 记录有促销的数目
    data.priceLowSize = undefined;  // !!!该数目只用于记录与上次访问相比 服务端所有收藏有降价的数目 并非depried接口返回的数据数目

    // 个人信息相关
    data.personal = {
        userEmail : undefined// 用户降价提醒使用的邮箱
    };

    var supportedType = ['all', 'depriced', 'promotion', 'depricedReminder'];
    var deleteAPI = 'delurls';
    // 不同类型需要的信息
    data.ref = {
        'all' : {
            api : 'myzhushou/collection/list',
            deleteApi : 'myzhushou/collection/delurls',
            target : 'list',
            apiTarget : 'list',
            apiSizeName : 'allsize',
            localSizeName : 'allsize'
        },
        'depriced' : {
            api : 'myzhushou/collection/pricelowlist',
            deleteApi : 'myzhushou/collection/delurls',
            target : 'pricelowlist',
            apiTarget : 'list',
            apiSizeName : 'allsize',
            localSizeName : 'depricedsize'
        },
        'promotion' : {
            api : 'myzhushou/collection/promotionlist',
            deleteApi : 'myzhushou/collection/delurls',
            target : 'promotionlist',
            apiTarget : 'list',
            apiSizeName : 'allsize',
            localSizeName : 'promotionsize'
        },
        'depricedReminder' : {
            api : 'pricehub/get_detail_subs',
            target : 'depricedReminderList',
            apiTarget : 'items',
            apiSizeName : 'total',
            localSizeName : 'depricedReminderSize'
        }
    };

    var failedReq = [];


    // 配置 end
    // -------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // 私有方法 start

    /**
     * 向服务端请求数据
     */
    // 供收藏夹api使用的参数
    var colletionsDefaultParam = {
        // 从0开始
        'start' : 0,
        'length' : DEFAULT_INIT_DATA_COUNTS
    };

    var _requestData = function (type, startId, n, callback) {

        if (!_.contains(supportedType, type)) {
            throw new Error('获取数据的类型错误');
        }

        var url;
        var params;
        switch(type) {
            case 'all':
            case 'depriced':
            case 'promotion':
                // 拼出来url
                params = _.clone(colletionsDefaultParam);
                params.start = startId;
                params.length = n;

                var temp = _.reduce(_.keys(params), function (memo, key) {
                    return memo  + key + '=' + params[key] + '&';
                }, '')

                url = URL_BASE + data.ref[type].api + '?' + temp.slice(0, temp.length - 1);

                break;
            case 'depricedReminder':
                // 降价提醒
                // 只提供page一个接口 page=1 对于0-9数据 page=2 对应10-19数据
                params = {
                    page : Math.ceil(startId/9)
                };
                var page = Math.ceil(startId/9);
                url = URL_BASE + data.ref[type].api + '?' + 'page=' + page;

                break;
        }

        // 增加时间戳
        url += '&t=' + (new Date().getTime());

        // jsonp 供浏览器无法跨域时进行本地测试
        var ajax = require('./jsonp.js');
        ajax({
            url : url,
            success : function (res) {
                callback(res);
            },
            error : function (res) {
                callback('net-error');
            }
        });

        // $.ajax({
        //     url : url,
        //     dataType : 'json',
        //     timeout : 5000,
        //     success : function (res) {
        //         // // 模拟猜你喜欢数据
        //         // var tempData = require('./guess.js');
        //         // var list = res.list;
        //         // _.each(list, function (item) {
        //         //     item.recmds = item.recmds ? item.recmds : tempData.list;
        //         // });

        //         // debugger;
        //         callback(res);
        //     },
        //     error : function (err) {
        //         callback('net-error');
        //         failedReq.push([type, startId, n, function (res) {
        //             callback(res);

        //         }]);
        //         console.log('服务请求出错', err);
        //     }
        // });


    };


    /**
     * 使用请求回来的数据更新现有本地存储
     * @param  {[type]} rawData 原始数据
     * @return {[type]}         [description]
     */
    var _updateLocal = function (rawData, type, startId, callback) {

        if (!_.isObject(rawData) || !_.isString(type)) {
            throw new Error('update 本地数据的参数出错');
        };

        var localSizeName = data.ref[type].localSizeName;
        var apiSizeName = data.ref[type].apiSizeName;
        var curListName = data.ref[type].target;
        var apiTarget = data.ref[type].apiTarget;

        if (type === 'all') {
            // 全部接口中带有需要高亮提示用户的降价数目和促销数目
            data.priceLowSize = rawData.priceLowSize;
        }

        if (isIE67) {
             _.each(rawData[apiTarget], function (item) {
                replaceBase64(item);

             });
        }

        if (data[localSizeName] < rawData[apiSizeName]) {
            // 返回来的数据中如果allsize有增加而非减少 说明用户有收藏新商品
            // 数目减少无需处理是因为在删除的回调中应该已经做过删除数据的处理
            // 数目增加的话，需要额外请求一次数据，补足队列首
            var increasedNum = rawData[apiSizeName] - data[localSizeName];
            _requestData(type, 0, increasedNum, function (raw) {
                data[curListName].length = raw[apiSizeName];
                [].splice.apply(data[curListName], [0, increasedNum].concat(raw[apiTarget]));
                msg.fire('updateMaxPageNum', Math.ceil(rawData[apiSizeName] /DEFAULT_PAGE_COUNTS), type);
                callback();
            });
        } else {
            [].splice.apply(data[curListName], [startId, rawData[apiTarget].length].concat(rawData[apiTarget]));
            msg.fire('updateMaxPageNum', Math.ceil(rawData[apiSizeName] /DEFAULT_PAGE_COUNTS), type);
            callback();
        }


    };

    /**
     *  从本地数据中获取指定类型，开始id，长度的数据
     */
    var _getLocalData = function (type, startId, n) {
        var curListName = data.ref[type].target;
        return data[curListName].slice(startId,  n + startId);
    };


    /**
     * 删除指定列表里的指定项
     * @param  {[type]} list [description]
     * @param  {[type]} urls [description]
     * @return {[type]}      [description]
     */
    var _deleteItemsInList = function (type, urls) {
        var inx, curItem;
        _.each(urls, function (url) {
            curItem = _.findWhere(data[data.ref[type].target], {
                        url : url
                    });
            if (_.isObject(curItem)) {
                inx = _.indexOf(data[data.ref[type].target], curItem);
                data[data.ref[type].target].splice(inx, 1);
                data[data.ref[type].localSizeName]--; // 更新本地数目
                msg.fire('updateMaxPageNum', Math.ceil(data[data.ref[type].localSizeName] / DEFAULT_PAGE_COUNTS), type); // 更新最大的页码
            }
        });
    };


    var _initialDataRequest = function (type, startId, n, callback) {
        var curListName = data.ref[type].target;
        var apiTarget = data.ref[type].apiTarget;
        var apiSizeName = data.ref[type].apiSizeName;
        var localSizeName = data.ref[type].localSizeName;

        _requestData(type, startId, n, function (rawData) {

            // 测试无数据的情况
            // if (type === 'depriced') {
            //     rawData[apiSizeName] = 0;
            //     rawData.list = [];
            // }

            if (rawData === 'net-error') {
                // 网络错误
                msg.fire('offline', type);
                return;
            }

            //!! 降价提醒的返回值内没有login类型
            if (type === 'all' && !rawData.login) {
                // 未登录状态下的请求只返回{login:false};
                msg.fire('noLogin');
                return;
            }

            if (!_.isNumber(rawData[apiSizeName])) {
                // throw new Error('数据返回的清单长度类型错误');
                // 无清单的认定为是没有收藏
                rawData[apiSizeName] = 0;
                rawData[apiTarget] = [];
            }

            data[localSizeName] = rawData[apiSizeName];
            data[curListName] = [];

            // 初始化的时候即按照服务端数据生成同等长度的数组
            // 空着的数据使用undefined占位
            data[curListName].length = rawData[apiSizeName];

            if (type === 'all') {
                // rawData.priceLowSize = 3;
                // rawData.promotionSize = 3;
                // rawData.pricehubSize = 3;
                // rawData.used = false;
                msg.fire('setTipNumber', 'depricedNumber', rawData.priceLowSize);
                msg.fire('setTipNumber', 'promotionNumber', rawData.promotionSize);
                msg.fire('setTipNumber', 'depricedReminderNumber', rawData.pricehubSize);
                if (rawData.used) {
                    msg.fire('showJifenGuide', rawData.jifenUrl);
                } else {
                    msg.fire('showNewUserGuide', rawData.jifenUrl);
                }
            }

            if (type === 'depricedReminder') {
                // rawData.descendNum = 3;
                // rawData.reachExpectNum = 3;
                // 降价提醒的数字
                msg.fire('setTipNumber', 'descendNum', rawData.descendNum);
                msg.fire('setTipNumber', 'reachExpectNum', rawData.reachExpectNum);
                // 设置降价提醒的邮箱地址
                msg.fire('setEmailData', rawData.email);
            }

            _updateLocal(rawData, type, startId, function () {
                if (rawData[apiSizeName] === 0) {
                    callback('none');
                } else {
                    callback(_getLocalData(type, startId, n));
                }
            });

        });
    };

    var _getAndUpdateLocalData = function (type, startId, n, callback) {
        var temp = _getLocalData(type, startId, n);

        // 判断本地数据中该段数据是否存在undefined
        // 若存在重新向服务端请求本段数据
        var hasUndefined = false;
        // 此处不适用原生的迭代方法，包括在此基础上的underscore some方法
        // 因按照标准 undefined的数组项在迭代的时候会被跳过
        for (var i = 0, l = temp.length; i < l;i++) {
            if (temp[i] === undefined) {
                hasUndefined = true;
                break;
            }
        }

        if (hasUndefined) {
            // 如果该区段里有空的数据；
            // 发起请求更换现有数据
            _requestData(type, startId, n, function (rawData) {

                if (rawData === 'net-error') {
                    // 网络错误
                    msg.fire('offline', type);
                    return;
                }

                _updateLocal(rawData, type, startId, function () {
                    callback(_getLocalData(type, startId, n));
                });
            });
        } else {
            // 数据完整 直接返回给回调执行
            callback(temp);
        }

    };

    // 私有方法 end
    // -------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // 暴露的接口 start

    /**
     * 视图获取数据的方法：
     * @param  {[type]}   type      [all | depriced]
     * @param  {[type]}   startId  [description]
     * @param  {[type]}   n         数据个数
     * @description  包括获取数据、本地更新数据、执行回调
     *               回调获得的数据只包括其必须的数据列表 不接触到原数据
     */
    data.getData = function (type, startId, n, callback) {
        var curListName = data.ref[type].target;
        var apiTarget = data.ref[type].apiTarget;
        var apiSizeName = data.ref[type].apiSizeName;
        var localSizeName = data.ref[type].localSizeName;

        if (!_.isFunction(callback)) {
            callback = $.noop;
        };

        if (data[localSizeName] === 0) {
            // 无收藏数据
            callback('none');
            return false;
        }

        if (data[localSizeName] === undefined) {
            // 首次请求该类型数据
            _initialDataRequest(type, startId, n, callback);

        } else {
            // 本地已经有该类型的数据
            // 获取本地数据 若本地数据该区段不完整 则向服务端请求该区段数据
            _getAndUpdateLocalData(type, startId, n, callback);
        };
    };

    /**
     * 删除指定数据
     * @param  {[url1, url2, ...]}   ids      实际上是对应的url列表
     * @param  {Function} callback [description]
     * @return {[type]}            [description]
     */
    data.deleteData = function (type, urls, callback) {

        if (!_.isArray(urls)) {
            if (_.isString(urls)) {
                urls = [urls]; // 支持传入单个url 自动转为数组
            } else {
                throw new Error('deletData 参数类型错误！');
            }
        }

        // 订阅类的网路同步单独处理 这里只处理收藏夹数据
        if (type === 'depricedReminder') {
            _deleteItemsInList('depricedReminder', urls);
            if (_.isFunction(callback)) {
                callback(urls);
            }
            return;
        }

        var deleteAPI = data.ref[type].deleteApi

        var resultUrl = '';
        var md5Urls = (_.map(urls, function (url) {
                    return md5(url);
                })).join('|');
        resultUrl = URL_BASE + deleteAPI + '?' + 'allmd5=' + md5Urls;
        // 成功的回调里：
        // 删除时需要同时更新两个列表

        // jsonp 供浏览器无法跨域时进行本地测试
        var ajax = require('./jsonp.js');
        ajax({
            url : resultUrl,
            success : function (res) {
                _deleteItemsInList('all', urls);
                _deleteItemsInList('depriced', urls);
                _deleteItemsInList('promotion', urls);
                callback();
            },
            error : function (res) {
                callback('net-error');
            }
        });
        // $.ajax({
        //     url : resultUrl,
        //     dataType : 'json'
        // }).done(function (res) {
        //     alert(2);
        //     // 删除两个列表里的该项数据
            // _deleteItemsInList('all', urls);
            // _deleteItemsInList('depriced', urls);
            // _deleteItemsInList('promotion', urls);
        //     callback();
        // });
    };

    /**
     * 重新发起之前失败的请求
     */
    data.retry =  function () {
        var params;
        do {
            params = failedReq.shift();
            _requestData.apply(this, params);
        } while (failedReq .length !== 0)
    };


    /**
     * 个人数据
     */
    data.userInfo = {
        getDepricedEmail : function () {
            return data.personal.userEmail;
        },
        changeDepricedEmail : function (email) {
            data.personal.userEmail = email;
        }
    };

    // 初始化：
    // 首次加载时向服务端请求默认10条数据，同时获取所有数据个数和降价了的数目
    data.init = function (callback) {
        data.getData('all', 0, DEFAULT_INIT_DATA_COUNTS, function () {
            callback();
            // data.getData('depricedReminder', 0);
        });
    }

    // 暴露的接口end
    // -------------------------------------------------------------------------
    window.data = data;

});
