import { message } from 'antd'
import * as service from '../services/index'
import URLS from '../constants/url'

export default {
    namespace: 'dataConnect',
    state: {
        originData: {
            listLoading: false,
            list: [],
            newOne: {},
            filterLabel: '',
            validInfo: {},
            filterItems: [ // 可选过滤字段
                { name: 'name', label: '链接名', type: 'string' },
            ],
            filterItem: { name: 'name', label: '链接名', type: 'string' }, // 已选过滤字段
        },
    },
    reducers: {
        setField(state, action) {
            const { name, value } = action;
            let obj = {};
            obj[name] = value;
            let newState = Object.assign({}, state, obj);
            return Object.assign({}, newState);
        },
        setFields(state, action) {
            const { fields } = action;
            let obj = {};
            fields.map(f => (obj[f.name] = f.value));
            let newState = Object.assign({}, state, obj);
            return Object.assign({}, newState);
        },
        list(state, action) {
            const data = action.data;
            return Object.assign({}, state, {list: data});
        },
        add(state, action) {
            let newOne = Object.assign({}, state.newOne);
            let list = state.list;
            newOne.key = new Date().getMilliseconds()+(Math.random()*100).toFixed(0);
            newOne.code = new Date().getMilliseconds()+(Math.random()*100).toFixed(0);
            list.push(newOne);
            return Object.assign({}, state, {list});
        },
        modify(state, action) {
            const { newOne } = state;
            let list = state.list;
            for(let i = 0; i < list.length; i++) {
                if(list[i].code === newOne.code) {
                    list[i] = Object.assign({}, newOne);
                    break;
                }
            }
            return Object.assign({}, state, {list});
        },
        delete(state, action) {
            const { model } = action;
            let { list } = state;
            for(let i = 0; i < list.length; i++) {
                if(list[i].code === model.code) {
                    list.splice(i, 1);
                }
            }
            return Object.assign({}, state, {list});

        },
        setSelected(state, action) {
            const { selected } = action;
            return Object.assign({}, state, {selected});
        },
        resetSelected(state, action) {
            return Object.assign({}, state, {selected: null});
        },
        setFilterItem(state, action) {
            const { item } = action;
            return Object.assign({}, state, {filterItem: item, filterLabel: ''});
        },
        setFilterLabel(state, action) {
            const { label } = action;
            return Object.assign({}, state, { filterLabel: label });
        },
        setNewModelField(state, action) {
            const { name, value } = action;
            let newOne = state.newOne;
            let validInfo = state.validInfo;
            newOne[name] = value;
            if(['dbType', 'address', 'port', 'dbName', 'userName', 'password'].indexOf(name) !== -1) {
                newOne.invalid = undefined;
            }
            
            return Object.assign({}, state, { newOne, validInfo });
        },
        setNewModelFields(state, action) {
            const { fields } = action;
            let newOne = state.newOne;
            for(let i = 0; i < fields.length; i++) {
                let n = fields[i]['name'];
                let v = fields[i]['value'];
                newOne[n] = v;

                // 如果改动了需要重新校验的项
                if(['dbType', 'address', 'port', 'dbName', 'userName', 'password'].indexOf(n) !== -1) {
                    newOne.invalid = undefined;
                }
            }
            return Object.assign({}, state, {newOne});
        },
        setNewModel(state, action) {
            const { model } = action;
            let newOne = Object.assign({}, model);
            newOne.invalid = undefined;
            return Object.assign({}, state, {newOne});
        },
        resetNewModel(state, action) {
            let newOne = state.newOne;
            delete newOne.name;
            // delete newOne.dbType;
            delete newOne.address;
            delete newOne.port;
            delete newOne.dbName;
            delete newOne.userName;
            delete newOne.password;
            delete newOne.description;
            delete newOne.demo;
            newOne.invalid = undefined;
            return Object.assign({}, state, {newOne});
        },
        setNewModelInvalid(state, action) {
            const { value } = action;
            let newOne = state.newOne;
            newOne.invalid = value;
            return Object.assign({}, state, {newOne});
        },
        reset(state, action) {
            let newState = Object.assign({}, state, state.originData);
            return Object.assign({}, newState);
        },
    },
    effects: {
        *fetchList(action, { select, call, put, takeEvery, takeLatest }) {
            const { pageNum, pageSize } = action;
            const body = {
                pageNum: pageNum || 1,
                pageSize: pageSize || 999999999
            }
            try {
                const dataConnect = yield select(state => state.present.dataConnect);
                if(!action.mandatory && dataConnect.list.length > 0) {
                    return;
                }
                if(!action.silent) {
                    yield put({ type: 'setField', name: 'listLoading', value: true });
                }
                const res = yield call(service.fetch, {
                    url: URLS.DATACONNECT_LIST,
                    method: 'GET',
                    body
                });
                if(!res.err && res.data.code > 0) {
                    let data = res.data.data.list.map((r, i) => {
                        return {
                            key: i,
                            code: r.id + '',
                            name: r.name,
                            dbName: r.dataName,
                            dbType: r.databaseType,
                            address: r.addrass,
                            port: r.port,
                            userName: r.userName,
                            password: r.passWord,
                            description: r.note,
                            demo: r.demo
                        }
                    });
                    yield put({ type: 'list', data });
                }else {
                    message.error('读取数据链接配置列表错误: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                message.error('读取数据链接配置列表错误: ' + e.message);
            }finally {
                yield put({ type: 'setField', name: 'listLoading', value: false });
            }
        },
        *remoteValidate(action, { select, call, put, takeEvery, takeLatest }) {
            const dataConnect = yield select(state => state.present.dataConnect);
            const model = dataConnect.newOne;
            try {
                // 设置validating为true
                yield put({ type: 'setNewModelField', name: 'validating', value: true });
                yield put({ type: 'setNewModelFields', fields: [
                    { name: 'name', value: model.name || '' },
                    { name: 'address', value: model.address || '' },
                    { name: 'port', value: model.port || '' },
                    { name: 'dbType', value: model.dbType || '' },
                    { name: 'dbName', value: model.dbName || '' },
                    { name: 'userName', value: model.userName || '' },
                    { name: 'password', value: model.password || '' },
                ] });
                // 调用检测接口检测连接配置是否合法
                let validBody = {
                    id: model.code,
                    name: model.name,
                    addrass: model.address,
                    port: model.port,
                    databaseType: model.dbType,
                    dataName: model.dbName,
                    userName: model.userName,
                    passWord: model.password
                }
                const res = yield call(service.fetch, {
                    url: URLS.DATACONNECT_VALIDATE,
                    body: validBody,
                    timeout: 30000
                });

                // 设置validating为false
                yield put({ type: 'setNewModelField', name: 'validating', value: false });

                if(!res.err && res.data.code > 0) {
                    // 如果合法
                    // 设置valid为true
                    yield put({ type: 'setNewModelInvalid', name: 'invalid', value: false });
                    message.success('测试通过');
                }else {
                    message.error('校验失败: ' + (res.err || res.data.msg));
                    yield put({ type: 'setNewModelInvalid', name: 'invalid', value: true });
                }
            }catch(e) {
                message.error('校验失败: ' + e.message);
                yield put({ type: 'setNewModelField', name: 'validating', value: false });
            }
        },
        *remoteAdd(action, { select, call, put, takeEvery, takeLatest }) {
            try {
                const dataConnect = yield select(state => state.present.dataConnect);
                const model = dataConnect.newOne;

                // 设置validating为true
                yield put({ type: 'setNewModelField', name: 'saving', value: true });

                let body = {
                    name: model.name,
                    addrass: model.address,
                    port: model.port,
                    databaseType: model.dbType,
                    dataName: model.dbName,
                    userName: model.userName,
                    passWord: model.password,
                    note: model.description
                }
                const res = yield call(service.fetch, {
                    url: URLS.DATACONNECT_ADD,
                    body: body,
                    timeout: 30000
                });
                yield put({ type: 'setNewModelField', name: 'saving', value: false });

                if(!res.err && res.data.code > 0) {
                    yield put({ type: 'setNewModelInvalid', name: 'invalid', value: false });
                    yield put({ type: 'fetchList', mandatory: true });
                    message.success('新增成功');
                    return true;
                }else {
                    message.error('新增失败: ' + (res.err || res.data.msg));
                    yield put({ type: 'setNewModelInvalid', name: 'invalid', value: true });
                    return false;
                }
            }catch(e) {
                message.error('新增失败: ' + e.message);
                yield put({ type: 'setNewModelField', name: 'saving', value: false });
                return false;
            }
        },
        *remoteModify(action, { select, call, put }) {
            try{
                const dataConnect = yield select(state => state.present.dataConnect);
                const model = dataConnect.newOne;

                // 设置validating为true
                yield put({ type: 'setNewModelField', name: 'saving', value: true });

                const code = action.code;

                let data = {
                    id: code,
                    name: model.name,
                    addrass: model.address,
                    port: model.port,
                    databaseType: model.dbType,
                    dataName: model.dbName,
                    userName: model.userName,
                    passWord: model.password,
                    note: model.description
                };
                const res = yield call(service.fetch, {
                    url: URLS.DATACONNECT_UPDATE,
                    body: data,
                    timeout: 30000
                });

                yield put({ type: 'setNewModelField', name: 'saving', value: false });

                if(!res.err && res.data.code > 0) {
                    yield put({ type: 'setNewModelInvalid', name: 'invalid', value: false });
                    yield put({ type: 'fetchList', mandatory: true });
                    message.success('修改成功');
                    return true;
                }else {
                    yield put({ type: 'setNewModelInvalid', name: 'invalid', value: true });
                    message.error('修改失败: ' + (res.err || res.data.msg));
                    return false;
                }
            }catch(e) {
                message.error('修改失败: ' + e.message);
                yield put({ type: 'setNewModelField', name: 'saving', value: false });
                return false;
            }
        },
        *remoteDelete(action, { select, call, put, takeEvery, takeLatest }) {
            const dataConnect = yield select(state => state.present.dataConnect);
            const code = action.code;
            let list = dataConnect.list;
            try {
                const res = yield call(service.fetch, {
                    url: URLS.DATACONNECT_DELETE,
                    body: code
                });
                if(!res.err && res.data.code > 0) {
                    for(let i = 0; i < list.length; i++) {
                        if((list[i].code+'') === (code+'')) {
                            list.splice(i, 1);
                            break;
                        }
                    }
                    yield put({ type: 'list', data: list });
                    message.success('删除成功');
                }else {
                    message.error('删除失败: ' + (res.err || res.data.msg));
                }
            }catch(e) {
                message.error('删除失败: ' + e.message);
            }
        }
    },
    subscriptions: {
        setup({ dispatch, history }) {
            dispatch({ type: 'reset' });
        }
    }
};