// Copyright 2020 Thomas Hintz
//
// This file is part of the Alpha Centauri Farming project.
//
// The Alpha Centauri Farming project is free software: you can
// redistribute it and/or modify it under the terms of the GNU General
// Public License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// The Alpha Centauri Farming project is distributed in the hope that
// it will be useful, but WITHOUT ANY WARRANTY; without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE.  See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with the Alpha Centauri Farming project.  If not, see
// <https://www.gnu.org/licenses/>.

import { UPDATE_GAME, UPDATE_PLAYER, GAME_STATE, SET_SELECTED_CARD, SET_CARDS,
         SPACE_PUSH_PLAYER, SPACE_CLEAR_PLAYERS,
         SET_OLD_MESSAGES, MESSAGE_PANEL_SPACE, MP_MOUSE,
         SET_MP_DIMS, MOVE_PLAYER, SET_NEXT_ACTION, NEXT_UI_ACTION,
         MARK_ACTION_CHANGE_HANDLED, NEXT_UI_ACTION_SILENT, ALERT, ALERT_HANDLED,
         AUTO_SKIP, MESSAGE, SET_HARVEST_TABLE, SET_CARD_ERROR,
         SET_MOVING_SKIP, SERVER_ERROR, REMOVE_PLAYER } from './actionTypes.js'
import { GAME_STATES } from '../../constants.js'
import { spaceContent, corners } from 'game.js'

const spaces =
      [[corners[0], 'buy', false],
       ['January', 'buy', false],
       ['January', 'buy', 'otb'],
       ['January', 'buy', false],
       ['January', 'buy', false],
       ['February','buy', false],
       ['February', 'buy', 'fate'],
       ['February', 'buy', false],
       ['February', 'buy', 'otb'],
       ['March', 'buy', false],
       ['March', 'buy', false],
       ['March', 'buy', false],
       ['March', 'buy', false],
       ['April', 'buy', 'otb'],
       [corners[1], 'buy', false],
       ['April', 'none', false],
       ['April', 'none', false],
       ['May', 'none', false],
       ['May', 'none', false],
       ['May', 'hay', false],
       ['May', 'hay', 'otb'],
       ['June', 'hay', false],
       ['June', 'hay', false],
       ['June', 'cherry', false],
       ['June', 'cherry', 'fate'],
       [corners[2], 'cherry', false],
       ['July', 'hay', false],
       ['July', 'hay', 'otb'],
       ['July', 'hay', false],
       ['July', 'wheat', false],
       ['August', 'wheat', false],
       ['August', 'wheat', false],
       ['August', 'wheat', false],
       ['August', 'wheat', false],
       ['September', 'hay', false],
       ['September', 'hay', 'otb'],
       ['September', 'cows', false],
       [corners[3], 'cows', false],
       ['September', 'cows', false],
       ['October', 'cows', false],
       ['October', 'hay', 'fate'],
       ['October', 'hay', 'otb'],
       ['October', 'apple', 'fate'],
       ['November', 'apple', 'otb'],
       ['November', 'apple', false],
       ['November', 'apple', false],
       ['November', 'corn', false],
       ['December', 'corn', false],
       ['December', 'corn', 'fate']]
      .map((s, i) => {
          return { month: s[0], description: spaceContent[i],
                   card: s[2],
                   type: s[1], key: i, players: [] }});

const initialState = {
    player: { cash: 5000,
              displayCash: 5000,
              lastCash: 5000,
              debt: 5000,
              spaces,
              state: GAME_STATES.turnEnded,
              assets: { hay: 10, grain: 10, fruit: 0, cows: 0, harvester: 0, tractor: 0, birthday: 0 },
              color: '',
              name: '',
              cards: [],
              revealedCards: [],
              ridges: { ridge1: 0, ridge2: 0, ridge3: 0, ridge4: 0 },
              space: 0,
              hayDoubled: false,
              cornDoubled: false,
              trade: {},
              ai: false
            },
    game: { calledAudit: false,
            currentPlayer: '',
            messages: [],
            otherPlayers: [],
            state: GAME_STATES.preTurn,
            turn: 0,
            oldMessages: [],
            name: '',
            host: '',
            settings: { downPayment: 0.2,
                        loanInterest: 0.2,
                        maxDebt: 50000,
                        auditThreshold: 250000,
                        startingOtbs: 2,
                        startingCash: 5000,
                        startingDebt: 5000 },
            readyToStart: false
          },
    ui: { card: { type: 'no-card', contents: '', total: 0 },
          cards: [],
          cardError: false,
          action: false,
          actionValue: null,
          nextAction: false,
          nextActionValue: null,
          actionChangeHandled: true,
          message: '',
          alerts: {},
          unhandledAlert: false,
          autoSkip: false,
          playerSpaces: {},
          movingSkip: false,
          harvestTable: false,
          exn: false },
    spaces: spaces,
    space: null,
    // message panel dimenions
    mpDims: { mouseX: 0, mouseY: 0,
              minWidth: 0, minHeight: 0, maxWidth: 0, maxHeight: 0,
              padding: 8 },
    profile: false,
    profileTurns: 500
}

export default function(state = initialState, action) {
    switch (action.type) {
    case UPDATE_GAME:
        return { ...state, game: { ...state.game, ...action.update }};
    case UPDATE_PLAYER:
        return { ...state, player: action.update };
    case GAME_STATE:
        return { ...state, game: { ...state.game, state: action.state } };
    case SET_SELECTED_CARD:
        return { ...state, ui: { ...state.ui, card: action.card }};
    case SET_CARDS:
        return { ...state, ui: { ...state.ui, cards: action.cards }};
    case SET_CARD_ERROR:
        return { ...state, ui: { ...state.ui, cardError: action.error }};
    case MOVE_PLAYER:
        if (action.oldSpace === action.newSpace) {
            return state;
        } else {
            return { ...state, spaces: state.spaces
                     .map((item, index) => {
                         if (index === action.newSpace &&
                             item.players.indexOf(action.player) === -1) {
                             return { ...item, players: [...item.players, action.player]};
                         } else if (index === action.oldSpace) {
                             return { ...item,
                                      players: item.players
                                      .filter(x => x !== action.player) };
                         }
                         return item;
                     }),
                     ui: { ...state.ui,
                           playerSpaces: { ...state.ui.playerSpaces,
                                           [action.player]: action.newSpace }}
                   };
        }
    case REMOVE_PLAYER:
        const playerSpace = state.ui.playerSpaces[action.color];
        return { ...state,
                 spaces: state.spaces.map((item, index) => {
                     if (index === playerSpace) {
                         return { ...item,
                                  players: item.players
                                  .filter(x => x !== action.color) };
                     }
                     return item;
                 }),
                 ui: { ...state.ui,
                       playerSpaces: { ...state.ui.playerSpaces,
                                       [action.player]: -1 }}
               };
    case SET_OLD_MESSAGES:
        return { ...state, oldMessages: action.messages };
    case MESSAGE_PANEL_SPACE:
        return { ...state, space: action.space };
    case MP_MOUSE:
        return { ...state, mpDims: { ...state.mpDims,
                                     mouseX: action.mouseX, mouseY: action.mouseY }};
    case SET_MP_DIMS:
        return { ...state, mpDims: { ...state.mpDims,
                                     minWidth: action.minWidth,
                                     minHeight: action.minHeight,
                                     maxWidth: action.maxWidth,
                                     maxHeight: action.maxHeight }};
    case SET_NEXT_ACTION:
        return { ...state, ui: { ...state.ui, nextAction: action.action,
                                 nextActionValue: action.value }};
    case NEXT_UI_ACTION:
        return { ...state, ui: { ...state.ui, action: state.ui.nextAction,
                                 actionValue: state.ui.nextActionValue,
                                 autoSkip: false,
                                 actionChangeHandled: !state.ui.nextAction }};
    case NEXT_UI_ACTION_SILENT: // don't set actionChangeHandled
        return { ...state, ui: { ...state.ui, action: state.ui.nextAction,
                                 actionValue: state.ui.nextActionValue }};
    case MARK_ACTION_CHANGE_HANDLED:
        return { ...state, ui: { ...state.ui, actionChangeHandled: true }};
    case ALERT:
        let existingAlert = state.ui.alerts[action.id];
        let alerts = { ...state.ui.alerts,
                       [action.id]: { type: action.value,
                                      id: action.id,
                                      contents: action.contents,
                                      handled: existingAlert ? existingAlert.handled : false }
                     };
        return { ...state, ui: { ...state.ui,
                                 alerts,
                                 unhandledAlert: Object.values(alerts).find(x => !x.handled)
                               }
               };
    case ALERT_HANDLED:
        alerts = { ...state.ui.alerts,
                   [action.id]: { ...state.ui.alerts[action.id],
                                  handled: true
                                }
                 };
        return { ...state, ui: { ...state.ui,
                                 alerts,
                                 unhandledAlert: Object.values(alerts).find(x => !x.handled)
                               }
               };
    case AUTO_SKIP:
        return { ...state, ui: { ...state.ui, autoSkip: action.component }};
    case MESSAGE:
        return { ...state, ui: { ...state.ui, message: action.message }};
    case SET_HARVEST_TABLE:
        return { ...state, ui: { ...state.ui, harvestTable: action.table }};
    case SET_MOVING_SKIP:
        return { ...state, ui: { ...state.ui, movingSkip: action.skip }};
    case SERVER_ERROR:
        return { ...state, ui: { ...state.ui, exn: action.exn }};
    default:
        return state;
    }
}
