import reformatSummary from '../utils/reformat/summary';
import reformatCountyCollection from '../utils/reformat/countyCollection';
import reformatBops from '../utils/reformat/bops';
import reformatDelegates from '../utils/reformat/delegates';
import reformatCallFeed from '../utils/reformat/callFeed';
import cycleCandidateMetadata from '../atoms/cycleCandidateMetadata';
import combinedMetadata from '../atoms/combinedMetadata';
import contestSummaryResults from '../atoms/contestSummaryResults';
import summaryCollectionContestIds from '../atoms/summaryCollectionContestIds';
import contestCountyResults from '../atoms/contestCountyResults';
import calendar from '../atoms/calendar';
import pagesManifest from '../atoms/pagesManifest';
import currentPage from '../atoms/currentPage';
import delegates from '../atoms/delegates';
import storyCollection from '../atoms/storyCollection';
import dataSource from '../atoms/dataSource';
import bops from '../atoms/bops';
import voteHistory from '../atoms/voteHistory';
import governors from '../atoms/governors';
import callFeed from '../atoms/callFeed';
import pollsClosing from '../atoms/pollsClosing';
const updateAtom = opts => {
  const {
    atom,
    set,
    fileKey,
    lastUpdated,
    getData
  } = opts;
  set(atom, old => {
    if (old && old.metadata.lastUpdated >= lastUpdated) return old;
    return {
      metadata: {
        fileKey,
        lastUpdated
      },
      data: getData(old)
    };
  });
};
const updateCycleCandidateMetadata = ({
  data,
  ...rest
}) => {
  data.forEach(meta => {
    const id = `cycle:candidate:${meta.id}`;
    updateAtom({
      atom: cycleCandidateMetadata(id),
      getData: () => ({
        ...meta,
        id
      }),
      ...rest
    });
  });
};
const updateCombinedMetadata = ({
  data,
  ...rest
}) => {
  const id = `contest:${data.contest.id}`;
  updateAtom({
    atom: combinedMetadata(id),
    getData: () => ({
      contest: {
        ...data.contest,
        id
      },
      candidates: Object.fromEntries(Object.values(data.candidates).map(candidate => {
        const cid = `candidate:${candidate.id}::${id}`;
        return [cid, {
          ...candidate,
          id: cid,
          contestId: id,
          cycleId: candidate.cycleId && `cycle:candidate:${candidate.cycleId}`
        }];
      }))
    }),
    ...rest
  });
};
const updateCombinedMetadataCollection = ({
  data,
  ...rest
}) => {
  data.forEach(meta => {
    updateCombinedMetadata({
      data: meta,
      ...rest
    });
  });
};
const updateSummary = ({
  data,
  ...rest
}) => {
  const id = `contest:${data.id}`;
  updateAtom({
    atom: contestSummaryResults(id),
    getData: () => reformatSummary(data),
    ...rest
  });
};
const updateSummaryCollection = ({
  data,
  ...rest
}) => {
  const id = `collection:${data.id}`;
  const contestIds = [];
  data.contests.forEach(contest => {
    updateSummary({
      data: contest,
      ...rest
    });
    contestIds.push(`contest:${contest.id}`);
  });
  if (data.bops) {
    updateAtom({
      atom: bops,
      getData: () => reformatBops(data.bops),
      ...rest
    });
  }
  updateAtom({
    atom: summaryCollectionContestIds(id),
    getData: () => contestIds,
    ...rest
  });
};
const updateCountyCollection = ({
  data,
  ...rest
}) => {
  const id = `contest:${data.id}`;
  updateAtom({
    atom: contestCountyResults(id),
    getData: () => reformatCountyCollection(data),
    ...rest
  });
};
const updateCalendar = ({
  data,
  ...rest
}) => {
  updateAtom({
    atom: calendar,
    getData: () => data,
    ...rest
  });
};
const updateStoryCollection = ({
  data,
  ...rest
}) => {
  updateAtom({
    atom: storyCollection(data.tag),
    getData: () => data,
    ...rest
  });
};
const updatePagesManifest = ({
  data,
  set
}) => {
  set(pagesManifest, data);
};
const updateCurrentPage = ({
  data,
  set
}) => {
  set(currentPage, data);
};
const updateDelegates = ({
  data,
  ...rest
}) => {
  const fmtData = reformatDelegates(data);
  fmtData.parties.forEach(party => {
    updateAtom({
      atom: delegates(party.party),
      getData: () => party,
      ...rest
    });
  });
};
const updateBops = ({
  data,
  ...rest
}) => {
  updateAtom({
    atom: bops,
    getData: () => reformatBops(data),
    ...rest
  });
};
const updateVoteHistory = ({
  data,
  ...rest
}) => {
  updateAtom({
    atom: voteHistory,
    getData: () => data,
    ...rest
  });
};
const updateGovernors = ({
  data,
  ...rest
}) => {
  updateAtom({
    atom: governors,
    getData: () => data,
    ...rest
  });
};
const updateCallFeed = ({
  data,
  ...rest
}) => {
  const id = `collection:${data.id}`;
  updateAtom({
    atom: callFeed(id),
    getData: () => reformatCallFeed(data),
    ...rest
  });
};
const updatePollsClosing = ({
  data,
  ...rest
}) => {
  updateAtom({
    atom: pollsClosing,
    getData: () => data,
    ...rest
  });
};
const updateFetchedDataFiles = function updateFetchedDataFiles(opts) {
  const {
    snapshot,
    set,
    values = []
  } = opts;
  values.forEach(val => {
    if (!val || !val.data) return;
    const setValue = set || ((...args) => snapshot.set(...args));
    const {
      config: {
        key,
        type
      },
      metadata: {
        lastUpdated
      },
      data
    } = val;
    const args = {
      set: setValue,
      fileKey: key,
      lastUpdated,
      data
    };
    setValue(dataSource(key), val);
    switch (type) {
      case 'cycle-candidate-collection':
        updateCycleCandidateMetadata(args);
        break;
      case 'combined-metadata':
        updateCombinedMetadata(args);
        break;
      case 'combined-metadata-collection':
        updateCombinedMetadataCollection(args);
        break;
      case 'summary':
        updateSummary(args);
        break;
      case 'summary-collection':
        updateSummaryCollection(args);
        break;
      case 'county-collection':
        updateCountyCollection(args);
        break;
      case 'calendar':
        updateCalendar(args);
        break;
      case 'story-collection':
        updateStoryCollection(args);
        break;
      case 'pages-manifest':
        updatePagesManifest(args);
        break;
      case 'current-page':
        updateCurrentPage(args);
        break;
      case 'delegates':
        updateDelegates(args);
        break;
      case 'bops':
        updateBops(args);
        break;
      case 'vote-history':
        updateVoteHistory(args);
        break;
      case 'governors':
        updateGovernors(args);
        break;
      case 'call-feed':
        updateCallFeed(args);
        break;
      case 'polls-closing':
        updatePollsClosing(args);
        break;
      default:
        break;
    }
  });
};
export default updateFetchedDataFiles;