// adapted from
// https://stackoverflow.com/questions/41791193/vuejs-reactive-binding-for-a-plugin-how-to/41801107#41801107
import Vue, { VueConstructor } from 'vue';

class ModalStore {
  vm: Vue;

  constructor() {
    this.vm = new Vue({
      data: () => ({
        component: '',
        payload: {},
      }),
    });
  }

  get state() {
    return this.vm.$data;
  }
}

interface Modal {
  state: any;
  component: string;
  payload?: any;
  confirm: (res: any) => void;
  open: (component: string, payload?: any) => Promise<(resolve: () => any, reject: () => any) => void>;
  cancel: () => void;
  _resolve: (r?: any) => any;
  _reject: (r?: any) => any;
}

declare module 'vue/types/vue' {
  interface Vue {
    $modal: Modal;
  }
}

const ModalPlugin = {
  install(Vue: VueConstructor) {
    const store = new ModalStore();

    const reset = () => {
      store.state.component = '';
      store.state.payload = {};
    };

    const modal: Modal = {
      state: store.state,
      component: store.state.component,
      payload: store.state.payload,
      open(component: string, payload?: any) {
        store.state.payload = payload;
        store.state.component = component;
        return new Promise((resolve, reject) => {
          this._resolve = resolve;
          this._reject = reject;
        });
      },
      confirm(res: any) {
        reset();
        this._resolve(res);
      },
      cancel() {
        reset();
        this._reject();
      },
      _resolve: () => {},
      _reject: () => {},
    };

    Vue.prototype.$modal = modal;
  },
};

export default ModalPlugin;
