export const MAX_POINTS = 2
export const BASE_POINTS = 1
export const MIN_POINTS = 0
export const EMPHASIS_POINTS = 2

export function getPartiesWithScores (answers, emphasized, partiesPositions) {
  const scorePointsGrid = getScorePointsGrid(answers, emphasized, partiesPositions)

  return partiesPositions.map(party => ({
    ...party,
    score: getTotalScorePerParty(party, scorePointsGrid)
  }))
}

export function getTotalMaxPoints (userAnswers, userEmphasized) {
  return userAnswers.map(answer => {
    const emphasis = userEmphasized.filter(e => e.thesis === answer.thesis).length >= 1
    return getMaxScorePerThesis(answer.position, emphasis)
  }).reduce((total, maxScorePerRow) => total + maxScorePerRow)
}

function getScorePointsGrid (userAnswers, userEmphasized, partiesPositions) {
  // 1. Iterate over scoringGrid
  // 2. Get user and party positions of each thesis
  // 3. Evaluate points based on calculation model for each party
  // 4. Get the maximum score per thesis
  // 5. Return a new object for each thesis row with results
  const scoringGrid = getScoringGrid(userAnswers, userEmphasized, partiesPositions)

  return scoringGrid.map(row => {
    const partiesFromRow = row.positions.filter(p => p.type === 'party')
    const userPosition = getUserPosition(row)
    const scores = partiesFromRow.map(party => ({
      party: party.party,
      score: evalPointsPerThesisPerParty(party.position, userPosition, row.emphasis)
    }))
    return {
      thesis: row.thesis,
      scores
    }
  })
}

function getTotalScorePerParty (party, scorePointsGrid) {
  return scorePointsGrid
    .map(thesis => thesis.scores.find(scores => scores.party === party.id).score)
    .reduce((total, score) => total + score, 0)
}

function getMaxScorePerThesis (userPosition, emphasis) {
  return userPosition === 'skipped' ? MIN_POINTS : emphasis ? MAX_POINTS * EMPHASIS_POINTS : MAX_POINTS
}

function getUserPosition (row) {
  return row.positions.find(p => p.type === 'user').position
}

// Grid example:
// [
//   {
//     thesis: 0,
//     emphasis: true,
//     positions: [
//       {type: 'party', party: 0, position: 'neutral'},
//       {type: 'party', party: 1, position: 'positive'},
//       {type: 'party', party: 2, position: 'negative'},
//       {type: 'party', party: 3, position: 'positive'},
//       {type: 'party', party: 4, position: 'positive'},
//       {type: 'party', party: 5, position: 'positive'},
//       {type: 'user', position: 'positive'}
//     ]
//   },
//   ...
// ]
function getScoringGrid (userAnswers, emphasizedTheses, parties) {
  const grid = userAnswers.map(answer => (
    {
      thesis: answer.thesis,
      emphasis: emphasizedTheses.filter(e => e.thesis === answer.thesis).length >= 1,
      positions: [
        ...getPartyPositions(answer.thesis, parties),
        ...[{ type: 'user', position: answer.position }]
      ]
    }
  ))
  return grid
}

function getPartyPositions (thesis, parties) {
  return parties.map(party => {
    const position = party.positions.find(p => p.thesis === thesis)
    return {
      type: 'party',
      party: party.id,
      position: (position && position.position) || 'skipped'
    }
  })
}

export function evalPointsPerThesisPerParty (partyPosition, userPosition, emphasis) {
  let score = 0
  if (partyPosition === 'skipped' || userPosition === 'skipped') {
    score = MIN_POINTS
  } else if (userPosition === partyPosition) {
    score = MAX_POINTS
  } else if (
    (userPosition === 'positive' && partyPosition === 'neutral') ||
    (userPosition === 'neutral' && partyPosition === 'positive') ||
    (userPosition === 'neutral' && partyPosition === 'negative') ||
    (userPosition === 'negative' && partyPosition === 'neutral')
  ) {
    score = BASE_POINTS
  } else if (
    (userPosition === 'positive' && partyPosition === 'negative') ||
    (userPosition === 'negative' && partyPosition === 'positive')
  ) {
    score = MIN_POINTS
  }

  return emphasis ? score * EMPHASIS_POINTS : score
}
