import {takeLatest} from 'redux-saga';
import {take, call, put, fork, cancel, select, race} from 'redux-saga/effects';
import {message} from 'antd';

export function invoke(command, api, msg) {
    return function*(data) {
        var ret;
        try {
            const result = yield call(api, data);
            if(typeof msg !== 'undefined'){
                message.success(msg + '成功!');
            }
            ret = {
                type: command + '_SUCCESS',
                result,
                data
            };
            yield put(ret);
        } catch (err) {
            console.error(msg, err);
            message.error(err);
            ret = {
                type: command + '_FAILED',
                err,
                data
            }
            yield put(ret);
        }
        return ret;
    }
}

export function watch(command, api, msg) {
    return function*() {
        while (true) {
            const {data} = yield take(command);
            yield fork(invoke(command, api, msg), data);
        }
    }
}

export function through(command, api, msg) {
    return function* (){
        while(true){
            yield take(command+'_START');
            const {submit} = yield race({
                submit: take(command+'_SUBMIT'),
                cancel: take(command+'_CANCEL')
            });
            var end = {};
            if(submit && submit.data){
                end = yield call(invoke(command, api, msg), submit.data);
            }else{
                console.log(command+'_CANCEL');
            }
            yield put({
                ...end,
                type: command+'_END'
            });
        }
    }
}


export function update(id, api) {
    return function*(data) {
        try {
            yield call(api, data);
            message.success('修改成功!');
            yield put({
                type: 'UPDATE_' + id + '_ITEM_SUCCESS',
                item: data
            });
        } catch (err) {
            console.error(err);
            message.error(err);
            yield put({
                type: 'UPDATE_' + id + '_ITEM_FAILED',
                err
            });
        }
    }
}

export function watchEdit(id, api) {
    return function*() {
        while (true) {
            yield take('UPDATE_' + id);
            yield put({
                type: 'UPDATE_' + id + '_START'
            });
            const {data} = yield race({
                data: take('UPDATE_' + id + '_ITEM'),
                canceled: take('CANCEL_UPDATE_' + id)
            });

            if (data && data.data) {
                yield fork(update(id, api), data.data);
            } else {
                yield put({
                    type: 'UPDATE_' + id + '_END'
                });
            }
        }
    }
}



export function index(id, api) {
    return function*(query) {
        try {
            const {list, total} = yield call(api, query);
            yield put({
                type: 'FETCH_' + id + '_LIST_SUCCESS',
                items: list,
                total
            });
        } catch (err) {
            console.error(err);
            message.error(err);
            yield put({
                type: 'FETCH_' + id + '_LIST_FAILED',
                err,
            });
        }
    }
}

export function watchIndex(id, api) {
    return function*() {
        while (true) {
            const {query} = yield take('FETCH_' + id + '_LIST');
            yield fork(index(id, api), query);
        }
    };
}

export function show(rid, api) {
    return function*(id) {
        try {
            const item = yield call(api, id);
            yield put({
                type: 'FETCH_' + rid + '_ITEM_SUCCESS',
                item
            });
        } catch (err) {
            console.error(err);
            message.error(err);
            yield put({
                type: 'FETCH_' + rid + '_ITEM_FAILED',
                err
            });
        }
    }
}

export function watchShow(rid, api) {
    return function*() {
        while (true) {
            const {id} = yield take('FETCH_' + rid + '_ITEM');
            yield fork(show(rid, api), id);
        }
    }
}

export function create(id, api) {
    return function*(data) {
        try {
            const item = yield call(api, data);
            yield put({
                type: 'CREATE_' + id + '_ITEM_SUCCESS',
                item: {...data, ...item, dateCreated: Date.now()}
            });
        } catch (err) {
            console.error(err);
            message.error(err);
            yield put({
                type: 'CREATE_' + id + '_ITEM_FAILED',
                err
            });
        }
    }
}

export function watchCreate(id, api) {
    return function*() {
        while (true) {
            const {item} = yield take('CREATE_' + id + '_ITEM');
            yield fork(create(id, api), item);
        }
    }
}



export function watchUpdate(id, api) {
    return function*() {
        while (true) {
            const {item} = yield take('UPDATE_' + id + '_ITEM');
            yield fork(update(id, api), item);
        }
    }
}

export function deleteItem(rid, api) {
    return function*(id) {
        try {
            yield call(api, id);
            message.success('删除成功!');
            yield put({
                type: 'DELETE_' + rid + '_ITEM_SUCCESS',
                removed: id,
            });
        } catch (err) {
            console.error(err);
            message.error(err);
            yield put({
                type: 'DELETE_' + rid + '_ITEM_FAILED',
                err
            });
        }
    }
}

export function watchDelete(rid, api) {
    return function*() {
        while (true) {
            const {id} = yield take('DELETE_' + rid + '_ITEM');
            yield fork(deleteItem(rid, api), id);
        }
    }
}


