import { computed, shallowRef } from 'vue';

import type { Resource } from '../../../../../../composables/resourcestore';
import type { Event } from '../../../../../../composables/eventstore';


export class InvalidStateTransition extends Error {}

export function useThisComponentStateMachine() {
  const state = shallowRef<(
    { type: 'normal' } |
    { type: 'eventEditDialog' } |
    { type: 'eventChangeDialog', details: { fromEvent: Event } } |
    { type: 'timelineSelection', details: { mode: (
      { type: 'move' } | { type: 'copy' } | { type: 'eventchange', details: {
        causeResources: Resource[],
        resourceHourUnfillRange: 'none' | 'time' | 'day',
      } }
    ), relatedEvent: Event } }
  )>({ type: 'normal' });

  function startEventEditDialog() {
    if(state.value.type !== 'normal') throw new InvalidStateTransition();
    state.value = { type: 'eventEditDialog' };
  }

  function endEventEditDialog() {
    if(state.value.type !== 'eventEditDialog') throw new InvalidStateTransition();
    state.value = { type: 'normal' };
  }

  function startEventChangeDialog(fromEvent: Event) {
    if(state.value.type !== 'normal') throw new InvalidStateTransition();
    state.value= { type: 'eventChangeDialog', details: { fromEvent } };
  }

  function proceedToEventChangeTimelineSelection(
    causeResources: Resource[],
    resourceHourUnfillRange: 'none' | 'time' | 'day',
  ) {
    if(state.value.type !== 'eventChangeDialog') throw new InvalidStateTransition();
    state.value = { type: 'timelineSelection', details: {
      relatedEvent: state.value.details.fromEvent, mode: {
        type: 'eventchange', details: { causeResources, resourceHourUnfillRange },
      },
    } };
  }

  function endEventChangeDialog() {
    if(state.value.type !== 'eventChangeDialog') throw new InvalidStateTransition();
    state.value = { type: 'normal' };
  }

  function startTimelineSelection(
    mode: 'move' | 'copy', relatedEvent: Event,
  ) {
    if(state.value.type !== 'normal') throw new InvalidStateTransition();
    state.value = {
      type: 'timelineSelection', details: { mode: { type: mode }, relatedEvent },
    };
  }

  function endTimelineSelection() {
    if(state.value.type !== 'timelineSelection') throw new InvalidStateTransition();
    state.value = { type: 'normal' };
  }

  return {
    state: computed(() => state.value),
    startEventEditDialog, endEventEditDialog,
    startEventChangeDialog, proceedToEventChangeTimelineSelection,
    endEventChangeDialog, startTimelineSelection, endTimelineSelection,
  };
}
