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

export function index(id, api){
    return function* (query) {
        try {
            const result = yield call(api, query);
            yield put({
                type: 'FETCH_' + id + '_LIST_SUCCESS',
                result
            });
        } catch (err) {
            console.log(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 result = yield call(api, id);
            yield put({
                type: 'FETCH_' + rid + '_ITEM_SUCCESS',
                result
            });
        } catch (err) {
            console.log(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 result = yield call(api, data);
            yield put({
                type: 'CREATE_' + id + '_ITEM_SUCCESS',
                result
            });
        } catch (err) {
            console.log(err);
            message.error(err);
            yield put({
                type: 'CREATE_' + id + '_ITEM_FAILED',
                err
            });
        }
    }
}

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

/*
export default class RESTful {
    constructor(id) {
        this.id = id;
    }




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

    watchCreate() {
        const self = this;
        return function*() {
            while (true) {
                const {data} = yield take('CREATE_' + self.id + '_ITEM');
                yield fork(self.create(), data);
            }
        }
    }

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

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

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

    delete() {
        const self = this;
        const {api} = this;

        return function*(id) {
            try {
                const result = yield call(api.show, id);
                yield put({
                    type: 'DELETE_' + self.id + '_ITEM_SUCCESS',
                    result
                });
            } catch (err) {
                console.log(err);
                message.error(err);
                yield put({
                    type: 'DELETE_' + self.id + '_ITEM_FAILED',
                    err
                });
            }
        }
    }

    watchDelete() {
        const self = this;
        return function*() {
            while (true) {
                const {id} = yield take('DELETE_' + self.id + '_ITEM');
                yield fork(self.delete(), id);
            }
        }
    }

    patch() {
        const {api, id} = this;
        return function*(data) {
            try {
                yield call(api.update, data);
                message.success('操作成功!');
                yield put({
                    type: 'PATCH_' + id + '_ITEM_SUCCESS',
                    item: data
                });
            } catch (err) {
                console.log(err);
                message.error(err);
                yield put({
                    type: 'PATCH_' + id + '_ITEM_FAILED',
                    err
                });
            }
        }
    }

    watchPatch() {
        const self = this;
        return function*() {
            while (true) {
                const {id} = yield take('PATCH_' + self.id + '_ITEM');
                yield fork(self.patch(), id);
            }
        }
    }

    watch() {
        const self = this;
        const mask = this.mask;
        const tasks = [
            self.watchIndex,
            self.watchCreate,
            //savenull,
            self.watchShow,
            //editnull,
            self.watchUpdate,
            self.watchDelete,
            self.watchPatch
        ];

        return function*() {
            tasks.forEach((task, index)=> {
                const mi = 1 << index;
                if (task && ((mask & mi ) === mi)) {
                    yield fork(task());
                }
            });
        }
    }

    actions() {
        const loadingFn = function (state) {
            return {...state, loading: true};
        };
        const failedFn = function (state, action) {
            return {...state, loading: false, err: action.err}
        };
        const editStartFn = function (state) {
            return {...state, isEdit: true}
        };
        const editEndFn = function (state) {
            return {...state, isEdit: false};
        };
        const itemsFn = function (state, action) {
            return {...state, loading: false, items: action.items, total: action.total}
        };
        const itemFn = function (state, action) {
            return {...state, loading: false, item: {...state.item, ...action.item}}
        };
        const id = this.id;

        return {
            ['INDEX_' + id ]: loadingFn,
            ['INDEX_' + id + '_SUCCESS']: itemsFn,
            ['INDEX_' + id + '_FAILED']: failedFn,
            ['SHOW_' + id]: loadingFn,
            ['SHOW_' + id + '_SUCCESS']: itemFn,
            ['SHOW_' + id + '_FAILED']: failedFn,
            ['CREATE_' + id]: loadingFn,
            ['CREATE_' + id + '_SUCCESS']: itemFn,
            ['CREATE_' + id + '_FAILED']: failedFn,
            ['UPDATE_' + id]: loadingFn,
            ['UPDATE_' + id + '_SUCCESS']: itemFn,
            ['UPDATE_' + id + '_FAILED']: failedFn,
            ['ENTER_EDIT' + id]: editStartFn,
            ['EXIT_EDIT_' + id]: editEndFn,
            ['DELETE_' + id]: loadingFn,
            ['DELETE_' + id + '_SUCCESS']: itemFn,
            ['DELETE_' + id + '_FAILED']: failedFn,
            ['PATCH_' + id]: loadingFn,
            ['PATCH_' + id + '_SUCCESS']: itemFn,
            ['PATCH_' + id + '_FAILED']: failedFn,
        }
    }
}
*/
