import { useState, useMemo, useCallback } from 'react';
import { useContestCollectionContests } from "../../../hooks/election/index.js";
import getPathCounts from './getPathCounts';
const usePaths = function usePaths(opts) {
  const {
    collectionId,
    stateConfigurations
  } = opts;
  const contests = useContestCollectionContests(collectionId);
  const [userConfigs, setUserConfigs] = useState({});
  const registerChoice = useCallback(({
    stateFips,
    party
  }) => {
    setUserConfigs(old => {
      const {
        [stateFips]: previousState,
        ...restConfigs
      } = old;
      if (!party) return restConfigs;
      return {
        ...restConfigs,
        [stateFips]: party
      };
    });
  }, []);

  /**
   * We need to know:
   * - which condition each state is in to drive the state select display
   * - the total that are "assigned" to each party, either by win or by user selection (270 minus this gives us the deficit for counting)
   * - the list of elector counts for each "unset" state (drives counting)
   * - the number of ways the unset elector counts can sum to the dem and gop deficits
   */
  const counts = useMemo(() => {
    if (!contests) {
      return {
        canonicalPaths: {
          dem: 0,
          gop: 0
        },
        userPaths: {
          dem: 0,
          gop: 0
        },
        canonicalTotals: {
          dem: 0,
          gop: 0
        },
        userTotals: {
          dem: 0,
          gop: 0
        },
        stateConditions: {},
        stateEvs: {}
      };
    }
    const countMeta = {
      stateConditions: {},
      stateEvs: {},
      canonicalUnsetElectorCounts: [],
      userUnsetElectorCounts: [],
      partyCanonicalTotals: {
        dem: 0,
        gop: 0
      },
      partyUserTotals: {
        dem: 0,
        gop: 0
      }
    };
    const getCondition = ({
      fips,
      winningParty
    }) => {
      if (winningParty === 'dem') return 'calledDem';
      if (winningParty === 'gop') return 'calledGop';
      if (userConfigs[fips] === 'dem') return 'selectedDem';
      if (userConfigs[fips] === 'gop') return 'selectedGop';
      if (stateConfigurations[fips] === 'dem') return 'calledDem';
      if (stateConfigurations[fips] === 'gop') return 'calledGop';
      return 'unset';
    };
    Object.values(contests).forEach(contest => {
      const {
        combinedMetadata: {
          contest: {
            stateFips
          }
        },
        summary,
        contestStatus: {
          winningParty
        }
      } = contest;
      const condition = getCondition({
        fips: stateFips,
        winningParty
      });
      countMeta.stateConditions[stateFips] = condition;
      const {
        evs
      } = summary;
      countMeta.stateEvs[stateFips] = evs;
      if (condition === 'unset') {
        countMeta.canonicalUnsetElectorCounts.push(evs);
        countMeta.userUnsetElectorCounts.push(evs);
      } else if (condition === 'calledDem') {
        countMeta.partyCanonicalTotals.dem += evs;
        countMeta.partyUserTotals.dem += evs;
      } else if (condition === 'calledGop') {
        countMeta.partyCanonicalTotals.gop += evs;
        countMeta.partyUserTotals.gop += evs;
      } else if (condition === 'selectedDem') {
        countMeta.partyUserTotals.dem += evs;
        countMeta.canonicalUnsetElectorCounts.push(evs);
      } else if (condition === 'selectedGop') {
        countMeta.partyUserTotals.gop += evs;
        countMeta.canonicalUnsetElectorCounts.push(evs);
      }
    });
    const canonicalPaths = getPathCounts({
      unsetElectorCounts: countMeta.canonicalUnsetElectorCounts,
      goal: 270,
      assigned: countMeta.partyCanonicalTotals
    });
    const userPaths = getPathCounts({
      unsetElectorCounts: countMeta.userUnsetElectorCounts,
      goal: 270,
      assigned: countMeta.partyUserTotals
    });
    return {
      canonicalPaths,
      userPaths,
      canonicalTotals: countMeta.partyCanonicalTotals,
      userTotals: countMeta.partyUserTotals,
      stateConditions: countMeta.stateConditions,
      stateEvs: countMeta.stateEvs
    };
  }, [contests, userConfigs]);
  const settableStates = useMemo(() => Object.entries(stateConfigurations).map(([state, condition]) => condition === 'unset' && state).filter(Boolean), [stateConfigurations]);
  return {
    canonicalPaths: counts.canonicalPaths,
    userPaths: counts.userPaths,
    canonicalTotals: counts.canonicalTotals,
    userTotals: counts.userTotals,
    stateConditions: counts.stateConditions,
    stateEvs: counts.stateEvs,
    settableStates,
    registerChoice
  };
};
export default usePaths;