import Solution from "./models/solution";
import SolutionState from "./models/solutionState";
import Protein from "./models/protein";
import _ from "lodash";
import { saveAs } from "file-saver"

export default {
    state: {
        solutionState: null,
        solution: null,
        solutionMeta: null,
        solutions: [],
        solution_count: 0
    },
    getters: {
        getSolutions(state) {
            return state.solutions;
        },
        getSolutionCount(state) {
            return state.solution_count;
        },
        getSolution(state) {
            return state.solution;
        },
        getSolutionMeta(state) {
            return state.solutionMeta;
        },
        getSolutionState(state) {
            return state.solutionState;
        }
    },
    mutations: {
        saveSolutions(state, { solutions }) {
            state.solutions = solutions;
        },
        setSolutionCount(state, { count }) {
            state.solution_count = count;
        },
        setSolution(state, { protein }) {
            state.solution = protein
        },
        setSolutionMeta(state, { solutionMeta }) {
            state.solutionMeta = solutionMeta
        },
        setSolutionState(state, solutionState) {
            state.solutionState = solutionState;
        }
    },
    actions: {
        checkSolutionState(context) {
            let statePromise = context.getters.getApi.get(`/graft/state`).then(
                (status) => context.commit('setSolutionState', new SolutionState(status.data.status,
                    status.data.order,
                    status.data.finished,
                    status.data.error,
                    status.data.canBeRetrieved))
            ).catch(err => {
                context.dispatch("setErrorMessage", { error: err });
                throw err;
            })

            context.dispatch("addAwaitable", {
                id: _.uniqueId("awaiting"),
                promise: statePromise,
                description: "Checking grafting state"
            });
            return statePromise;
        },

        downloadSolutions(context, { page, solutionsPerPage, sortBy, descending }) {
            let solutionsPromise = context.getters.getApi.get(`/score/${solutionsPerPage}/${page}/${sortBy}/${descending}`).then(
                (solutions) => {
                    let solutionObjects = []
                    for (let rawSolution of solutions.data) {
                        solutionObjects.push(new Solution(rawSolution.GRAFT_MUTANT_ID,
                            rawSolution.INDEX,
                            rawSolution.MODELLER_DOPE_SCORE,
                            rawSolution.ROSETTA_FASTRELAX_SCORE,
                            rawSolution.INSERT_COUNT,
                            rawSolution.GRAFT_MUTANT_SEQUENCE))
                    }
                    context.commit('saveSolutions', { solutions: solutionObjects })
                }
            ).catch(err => {
                context.dispatch("setErrorMessage", { error: err });
                throw err;
            })

            context.dispatch("addAwaitable", {
                id: _.uniqueId("awaiting"),
                promise: solutionsPromise,
                description: "Downloading solution table"
            });
            return solutionsPromise
        },

        downloadSolutionCount(context) {
            let solutionCountPromise = context.getters.getApi.get(`/scores_count`).then(
                (solution_count) => {
                    context.commit('setSolutionCount', solution_count.data)
                }
            ).catch(err => {
                context.dispatch("setErrorMessage", { error: err });
                throw err;
            })
            context.dispatch("addAwaitable", {
                id: _.uniqueId("awaiting"),
                promise: solutionCountPromise,
                description: "Getting the solution count"
            });
            return solutionCountPromise
        },

        downloadSolution(context, { name }) {
            let pdbPromise = context.getters.getApi.get(`/solution/${name}/pdb`);

            pdbPromise.then((pdb) => {
                let dsspPromise = context.getters.getApi.get(`/solution/${name}/dssp`)
                context.dispatch("addAwaitable", {
                    id: _.uniqueId("awaiting"),
                    promise: dsspPromise,
                    description: "Computing DSSP for solution"
                });
                dsspPromise.then((dssp) => {
                    let solution = new Protein(name, pdb.data, dssp.data, "A", "solution", true);
                    context.commit("setSolution", { protein: solution })
                })
            }).catch(err => {
                context.dispatch("setErrorMessage", { error: err });
                throw err;
            })

            context.dispatch("addAwaitable", {
                id: _.uniqueId("awaiting"),
                promise: pdbPromise,
                description: "Downloading solution PDB"
            });



            // return Promise.allSettled([pdbPromise, dsspPromise]).then(
            //     ([pdb, dssp]) => {

            //     }
            // )
        },
        userDownloadScoreTable(context) {
            let solutionsZipPromise = context.getters.getApi.get(`/score_table.tsv`, {
                responseType: "blob"
            }).then((response) => {
                var blob = new Blob([response.data], {
                    type: "text/tsv;charset=utf-8",
                });
                saveAs(
                    blob,
                    `score_table.tsv`
                );
            });

            context.dispatch("addAwaitable", {
                id: _.uniqueId("awaiting"),
                promise: solutionsZipPromise,
                description: "Downloading score table"
            });
        },
        userDownloadAllSolutions(context) {
            let solutionsZipPromise = context.getters.getApi.get(`/results.zip`, {
                responseType: "blob"
            }).then((response) => {
                var blob = new Blob([response.data], {
                    type: "application/zip",
                });
                saveAs(
                    blob,
                    `solutions.zip`
                );
            });

            context.dispatch("addAwaitable", {
                id: _.uniqueId("awaiting"),
                promise: solutionsZipPromise,
                description: "Downloading score table"
            });
        },

        userDownloadSelectedSolution(context) {
            let solutionsZipPromise = context.getters.getApi.get(`/solution/${context.getters.getSolutionMeta.name}/pdb`, {
                responseType: "blob"
            }).then((response) => {
                var blob = new Blob([response.data], {
                    type: "chemical/x-pdb",
                });
                saveAs(
                    blob,
                    `${context.getters.getSolutionMeta.name}.pdb`
                );
            });

            context.dispatch("addAwaitable", {
                id: _.uniqueId("awaiting"),
                promise: solutionsZipPromise,
                description: "Downloading score table"
            });

        },

    }



}