<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Database\QueryException;
use DB;

class MobileController extends Controller {

    const UNIQUE_KEY_VIOLATION = 2627;
    const ERROR_CODE = 1;

    public function redirect(Request $request) {
        $data = $request->json()->all();

        return response($data, 200);
    }

    /**
     * Get all data from an owner and respond with it.
     */
    public function login(Request $request)
    {
        $data = $request->json()->all();
        $owner_email = $data['email'];

        $query = 'SELECT * FROM users WHERE email = ?';

        $result_set = DB::select($query, [$owner_email]);
        $owner_id = $result_set[0]->id;

        $clubs = $this->get_clubs($owner_email);
        $groups = $this->get_groups($owner_email);
        $players = $this->get_players($owner_email);
        $club_members = $this->get_club_memberships($owner_email);
        $group_members = $this->get_group_memberships($owner_email);
        $stations = $this->get_stations();

        return response([
            'success' => 'All Agineek data returned!', 'id' => $owner_id,
            'clubs' => $clubs,
            'groups' => $groups,
            'players' => $players,
            'groupMemberships' => $group_members,
            'clubMemberships' => $club_members,
            'stations'=> $stations
        ], 200);
    }

    /**
     * Upload and sync data from an android phone.
     */
    public function uploadData(Request $request) {
        $data = $request->json()->all();

        try {
            $stations = $this->uploadStations($data['stations']);
            $station_id_swap = $this->station_id_swap($stations,$data['games']);
            $games =$this->uploadGames($station_id_swap);
            $club_id_swap = $this->uploadClubs($data['clubs'], $data['ownerID']);
            $groups = $this->club_id_swap($club_id_swap, $data['groups']);
            $group_id_swap = $this->uploadGroups($groups);
            $player_id_swap = $this->uploadPlayers($data['players']);
            $club_memberships = $this->club_id_swap($club_id_swap, $data['clubMemberships']);
            $club_memberships = $this->player_id_swap($player_id_swap, $club_memberships);
            $group_memberships = $this->group_id_swap($group_id_swap, $data['groupMemberships']);
            $group_memberships = $this->player_id_swap($player_id_swap, $group_memberships);
            $this->uploadClubMemberships($club_memberships);
            $this->uploadGroupMemberships($group_memberships);
            $session_id_swap = $this->uploadSessions($data['sessions']);
            $sessions_data = $this->player_id_swap($player_id_swap, $data['sessionsData']);
            $sessions_data = $this->session_id_swap($session_id_swap, $sessions_data);
            $sessions_data = $this->swap_game_ids($games,$sessions_data);
            $this->uploadSessionsData($sessions_data);

            if (empty($club_id_swap)) {
                $club_id_swap = (object) array();
            }

            if (empty($group_id_swap)) {
                $group_id_swap = (object) array();
            }

            if (empty($player_id_swap)) {
                $player_id_swap = (object) array();
            }

            if (empty($session_id_swap)) {
                $session_id_swap = (object) array();
            }

            if (empty($games)) {
                $games =(object) array();
            }

            if (empty($club_memberships)) {
                $club_memberships=(object) array();
            }

            if (empty($group_memberships)) {
                $group_memberships =(object)array();
            }

            if (empty($stations)) {
                $stations=(object) array();
            }

            return response([
                'success' => 'All data uploaded!', 'clubIDs' => $club_id_swap,
                'playerIDs' => $player_id_swap, 'groupIDs' => $group_id_swap, 'clubMemberships' => $club_memberships,
                'groupMemberships' => $group_memberships, 'stations' => $stations], 200);
        } catch (QueryException $err) {
            $err_string = json_encode($err);
            $err_json = json_decode($err_string);
            return response(['sqlError' => $err_json], 500);
        }
    }

    /*  START OF DATA UPLOAD FUNCTIONS */

    private function uploadSessions($sessions) {
        $session_id_swap = array();

        foreach ($sessions as $session) {
            $actual_id = DB::table('sessions')
                ->insertGetId([
                    'creation_date' => $session['sessionDate']
                ]);

            $session_id_swap[$session['sessionID']] = $actual_id;
        }

        return $session_id_swap;
    }

    /**
     * Swaps the sessionID keys in objects with the corresponding ones in session_ids
     */
    private function session_id_swap($session_ids, $objects) {
        $data = [];

        foreach ($objects as $object) {
            if (array_key_exists($object['sessionID'], $session_ids)) {
                $object['sessionID'] = $session_ids[$object['sessionID']];
            }
            array_push($data, $object);
        }

        return $data;
    }

    private function uploadSessionsData($sessions_data) {
        foreach ($sessions_data as $session_data) {
            DB::table('session_data')->insert([
                'session_id' => $session_data['sessionID'],
                'hits' => $session_data['hits'],
                'misses' => $session_data['misses'],
                'accuracy' =>$session_data['accuracy'],
                'game_id'=>$session_data['gameID'],
                'player_id' => $session_data['playerID'],
                'game_type' => $session_data['type'],
                'time_sequence' =>$session_data['time_sequence'],
                'pad_arrangement' =>$session_data['pad_arrangement']]);
        }
    }

    private function uploadGames($games) {
        $data = [];

        foreach ($games as $game){
            $actual_id = DB::table('game')->insertGetId([
                'sequence' => $game['sequence'],
                'game_mode' => $game['mode'],
                'game_time' => $game['time'],
                'delay_time' => $game['delay_time'],
                'num_of_pads' => $game['num_of_pads'],
                'game_description' => $game['description'],
                'game_type' => $game['type'],
                'station_id' => $game['station_id'],
                'pad_light_up_time'=>$game['pad_light_up_time']
            ]);
            //This will return all the new game ids
            $data[$game['gameID']] = $actual_id;
        }

        return $data;
    }

    /**
     * Swaps the sessionID keys in objects with the corresponding ones in session_ids
     * Used to get the correct game_id of the uploaded gameID.
     */
    private function swap_game_ids($games,$objects) {
        $data =[];

        foreach ($objects as $object) {
            if (array_key_exists($object['gameID'], $games)) {
                $object['gameID'] = $games[$object['gameID']];
            }

            array_push($data, $object);
        }

        return $data;

    }

    private function uploadStations($stations) {
        $data=[];

        foreach ($stations as $station) {
            $actual_id = DB::table('stations')->insertGetId([
                'station_name' =>$station['station_name'],
                'num_of_pads' => $station['num_of_pads'],
                'pads'=>$station['pads'],
                'description'=>$station['description'],
                'rectangle_attributes'=>$station['rectangle_attributes']
            ]);

            $data[$station['station_id']]=$actual_id;
        }

        return $data;
    }

    private function station_id_swap($stations,$objects) {
        $data =[];

        foreach ($objects as $object) {
            if (array_key_exists($object['station_id'], $stations)) {
                $object['station_id'] = $stations[$object['station_id']];
            }

            array_push($data, $object);
        }

        return $data;
    }

    private function uploadClubs($clubs, $owner_id) {
        $club_id_swap = [];

        foreach ($clubs as $club) {
            $online_clud_id = DB::table('clubs')
                ->insertGetId([
                    'owner_id' => $owner_id,
                    'club_name' => $club['clubName'],
                    'creation_date' => $club['creationDate'],
                ]);

            $club_id_swap[$club['clubID']] = $online_clud_id;
        }

        return $club_id_swap;
    }

    private function uploadGroups($groups) {
        $group_id_swap = [];

        foreach ($groups as $group) {
            $online_group_id = DB::table('groups')
                ->insertGetId([
                    'club_id' => $group['clubID'],
                    'group_name' => $group['groupName'],
                    'creation_date' => $group['creationDate'],
                    'group_desc' => $group['groupDescription']
                ]);

            $group_id_swap[$group['groupID']] = $online_group_id;
        }

        return $group_id_swap;
    }

    private function uploadPlayers($players) {
        $player_id_swap = [];

        foreach ($players as $player) {
            $online_player_id = DB::table('players')
                ->insertGetId([
                    'email' => $player['email'],
                    'phone_number' => $player['phoneNumber'],
                    'first_name' => $player['firstName'],
                    'last_name' => $player['lastName'],
                    'date_of_birth' => $player['birthDate'],
                    'creation_date' => $player['creationDate']
                ]);

            $player_id_swap[$player['playerID']] = $online_player_id;
        }

        return $player_id_swap;
    }

    /**
     * Swaps the clubID keys in objects with the corresponding ones in club_ids.
     * Used to keep the online clubID's and the local clubID's in sync.
     */
    private function club_id_swap($club_ids, $objects) {
        $data = [];

        foreach ($objects as $object) {
            if (array_key_exists($object['clubID'], $club_ids)) {
                $object['clubID'] = $club_ids[$object['clubID']];
            }
            array_push($data, $object);
        }

        return $data;
    }

    /**
     * Swaps the groupID keys in objects with the corresponding ones in group_ids.
     * Used to keep the online groupID's and the local groupID's in sync.
     */
    private function group_id_swap($group_ids, $objects) {
        $data = [];

        foreach ($objects as $object) {
            if (array_key_exists($object['groupID'], $group_ids)) {
                $object['groupID'] = $group_ids[$object['groupID']];
            }
            array_push($data, $object);
        }

        return $data;
    }

    /**
     * Swaps the playerID keys in objects with the corresponding ones in player_ids.
     * Used to keep the online playerID's and the local playerID's in sync.
     */
    private function player_id_swap($player_ids, $objects) {
        $data = [];

        foreach ($objects as $object) {
            if (array_key_exists($object['playerID'], $player_ids)) {
                $object['playerID'] = $player_ids[$object['playerID']];
            }

            array_push($data, $object);
        }

        return $data;
    }

    private function uploadClubMemberships($club_memberships) {
        foreach ($club_memberships as $club_membership) {
            DB::table('club_memberships')
                ->insert([
                    'club_id' => $club_membership['clubID'],
                    'player_id' => $club_membership['playerID']
                ]);
        }
    }

    private function uploadGroupMemberships($group_memberships) {
        foreach ($group_memberships as $group_membership) {
            DB::table('club_group_membership')->insert([
                'group_id' => $group_membership['groupID'],
                'player_id' => $group_membership['playerID']
            ]);
        }
    }

    /* END OF DATA UPLOAD FUNCTIONS */


    /* START OF DATA SYNCING FUNCTIONS */
    private function get_clubs($email) {
        $get_clubs = 'CALL GetClubs (?)';

        $result_set = DB::select($get_clubs, [$email]);

        $clubs = array();

        foreach($result_set as $row) {
            array_push($clubs, [
                'clubID' => $row->club_id,
                'ownerID' => $row->owner_id,
                'clubName' => $row->club_name,
                'creationDate' => $row->creation_date,
                'description' => ' '
            ]);
        }

        return $clubs;
    }

    private function get_groups($email) {
        $get_groups = 'CALL GetGroups (?)';

        $result_set = DB::select($get_groups, [$email]);

        $groups = array();

        foreach($result_set as $row) {
            array_push($groups, [
                'groupID' => $row->group_id,
                'clubID' => $row->club_id,
                'groupName' => $row->group_name,
                'creationDate' => $row->creation_date,
                'description' => $row->group_desc
            ]);
        }

        return $groups;
    }

    private function get_club_memberships($email) {
        $get_club_members = 'CALL GetClubMemberships (?)';

        $result_set = DB::select($get_club_members, [$email]);
        $club_members = [];

        foreach($result_set as $row) {
            array_push($club_members,[
                'clubID' => $row->club_id,
                'playerID' => $row->player_id
            ]);
        }

        return $club_members;
    }

    private function get_group_memberships($email) {
        $get_group_members = 'CALL GetGroupMemberships (?)';

        $result_set = DB::select($get_group_members, [$email]);
        $group_members = [];

        foreach($result_set as $row) {
            array_push($group_members,[
                'groupID' => $row->group_id, 'playerID' => $row->player_id
            ]);
        }

        return $group_members;
    }

    private function get_stations(){
        $res = DB::table('stations')->get();

        $stations =[];

        foreach ($res as $station){
            array_push($stations, [
                'station_id'=>$station->station_id,
                'station_name'=>$station->station_name,
                'pad_arrangement_name'=>$station->pad_arrangement_name,
                'pad_arrangement_image'=>$station->pad_arrangement_image,
                'num_of_pads'=>$station->num_of_pads,
                'pads'=>$station->pads,
                'description'=>$station->description,
                'rectangle_attributes'=>$station->rectangle_attributes]);
        }

        return $stations;
    }

    private function get_players($email) {
        $get_players = 'CALL GetPlayers (?)';

        $result_set = DB::select($get_players, [$email]);
        $players = [];

        foreach ($result_set as $row) {
            array_push($players, [
                'playerID' => $row->player_id,
                'email' => $row->email,
                'rating' => $row->rating,
                'phoneNumber' => $row->phone_number,
                'firstName' => $row->first_name, 'lastName' => $row->last_name,
                'birthDate' => $row->date_of_birth, 'creationDate' => $row->creation_date
            ]);
        }

        return $players;
    }

    /* END OF DATA SYNCING FUNCTIONS */
}
