import express from 'express';
import socketIo from 'socket.io';
import http from 'http';
import cors from 'cors';
import mysql from 'mysql';
import { v1 } from 'uuid';

import { IJankenSelect, IJankenResult } from './models/message';

const port: number = 8080;
const app: express.Express = express();
const httpServer: http.Server = http.createServer(app);
const io: socketIo.Server = socketIo(httpServer);

const tournaments: Record<string, number> = {};
const players: Record<string, number> = {};
const connection = mysql.createPool({
  connectionLimit: 10,
  host: 'test-db.csmrqtei38qi.ap-northeast-1.rds.amazonaws.com',
  user: 'admin',
  password: '12341234',
  database: 'catherine_league'
});
connection.query(
  `SELECT id, tournament_key
    FROM tournaments`,
  (error: mysql.MysqlError | null, results: any) => {
    if (error) {
      return;
    }
    if (results.length > 0) {
      results.forEach((result: any) => {
        tournaments[result.tournament_key] = result.id;
      });
    }
  }
);
connection.query(
  `SELECT id, player_key FROM players;`,
  (error: mysql.MysqlError | null, results: any) => {
    if (error) {
      console.log(error);
      return;
    }
    if (results.length > 0) {
      results.forEach((result: any) => {
        players[result.player_key] = result.id;
      });
    }
  }
);
if (process.env.NODE_ENV === 'development') {
  app.use(cors());
  app.options('*', cors());
}

app.get('/api/players/:key', (req: any, res: any) => {
  if (req.params && req.params.key && tournaments[req.params.key]) {
    const sqlToPrepare = `SELECT p.id, p.player_key, p.player_name,p.description,p.image,c.name_id, c.name, c.name_jp
    FROM players p
    JOIN player_to_tournament ptt
      on p.id = ptt.player_id
    JOIN characters c
      on c.id = p.character_id
    where ptt.tournament_id = ?`;
    const sql = mysql.format(sqlToPrepare, [tournaments[req.params.key]]);
    connection.query(sql,
      (error: mysql.MysqlError | null, results: any) => {
        if (error) {
          console.error(error);
          // players not found
        } else {
          res.send(results);
        }
      }
    );
  } else {
    // send error
  }
});
app.get('/api/players', (req: any, res: any) => {
  connection.query(
    `SELECT p.id, p.player_key, p.player_name,p.description,p.image,c.name_id, c.name, c.name_jp
      FROM players p
      JOIN characters c
        on c.id = p.character_id`,
    (error: mysql.MysqlError | null, results: any) => {
      if (error) {
        console.log(error);
        // players not found
      } else {
        res.send(results);
      }
    }
  );
});
app.get('/api/guide', (req: any, res: any) => {
  connection.query(
    `SELECT *
      FROM guide`,
    (error: mysql.MysqlError | null, results: any) => {
      if (error) {
        console.log(error);
        res.send([]);
      } else {
        res.send(results);
      }
    }
  );
});
app.get('/api/archive', (req: any, res: any) => {
  connection.query(
    `SELECT *
      FROM archive`,
    (error: mysql.MysqlError | null, results: any) => {
      if (error) {
        console.log(error);
        res.send([]);
      } else {
        res.send(results);
      }
    }
  );
});
app.get('/api/contact', (req: any, res: any) => {
  connection.query(
    `SELECT *
      FROM contact`,
    (error: mysql.MysqlError | null, results: any) => {
      if (error) {
        console.log(error);
        res.send([]);
      } else {
        res.send(results);
      }
    }
  );
});

app.use('/players', express.static('client'));
app.use('/tournaments*', express.static('client'));
app.use('/about', express.static('client'));
app.use('/guide', express.static('client'));
app.use('/archive', express.static('client'));
app.use('/contact', express.static('client'));
app.use('/tool', express.static('tool'));
app.use(express.static('client'));

httpServer.listen(port, () => {
  console.log(`listening to port ${port}`);
});

// Janken Tool

let room: boolean = false;
let playerOne: string = '';
let playerTwo: string = '';
let playerOneOption: string = '';
let playerTwoOption: string = '';
let stages: string[] = [];
let currentIndex: number = 0;
const defaultStages: string[] = ['cementery', 'prison', 'torture', 'inquisition', 'quadrangle', 'clock', 'spiral', 'empireo', 'cathedral', 'close', 'arrange'];


io.on('connection', (socket: socketIo.Socket) => {
  socket.on('disconnect', () => {
    console.log('disconnect');
  });

  socket.on('exitGame', () => {
    console.log('exitGame');
    io.emit('exitGame');
    room = false;
    initRoom();
    Object.keys(io.sockets.sockets).forEach((s) => {
      io.sockets.sockets[s].disconnect(true);
    });
  });
  socket.on('janken', (data: IJankenSelect) => {
    console.log('janken', data);
    if (playerOne === data.userName) {
      playerOneOption = data.option;
    } else if (playerTwo === data.userName) {
      playerTwoOption = data.option;
    }
    console.log('playerOneOption',playerOneOption);
    console.log('playerTwoOption',playerTwoOption);
    if (playerOneOption !== '' && playerTwoOption !== '') {
      const message: IJankenResult = {
        playerOne,
        playerOneOption,
        playerTwo,
        playerTwoOption
      }
      io.emit('jankenResult', message);
    }
  });
  socket.on('registerUser', (data: string) => {
    console.log('registerUser', data);
    if (playerOne === '') {
      playerOne = data;
      socket.emit('registerUser', data);
    } else if (playerTwo === '') {
      playerTwo = data;
      socket.emit('registerUser', data);
    }
    const message = {
      playerOne: playerOne,
      playerTwo: playerTwo,
    };
    console.log()
    io.emit('login', message);
  });
  socket.on('moveToStage', () => {
    console.log('moveToStage');
    stages = shuffle(defaultStages);
    currentIndex = 0;
    io.emit('stages', stages);
  });
  socket.on('nextIndex', () => {
    console.log('nextIndex');
    if (currentIndex < stages.length) {
      currentIndex += 1;
      io.emit('updateIndex', currentIndex);
    }
  });
  socket.on('againGame', () => {
    console.log('againGame');
    io.emit('againGame');
    playerOneOption = '';
    playerTwoOption = '';
  });
  socket.on('previousIndex', () => {
    console.log('previousIndex');
    if (currentIndex > 0) {
      currentIndex -= 1;
      io.emit('updateIndex', currentIndex);
    }
  });
  if (!room) {
    // create new room
    initRoom();
    room = true;
    const message = {
      playerOne: '',
      playerTwo: '',
    };
    socket.emit('login', message);
  }
  else {
    if (playerOne === '' || playerTwo === '' || playerOneOption === '' || playerTwoOption === '') {
      const message = {
        playerOne: playerOne,
        playerTwo: playerTwo,
      };
      socket.emit('login', message);
    } else {
      const message = {
        stages,
        currentIndex
      }
      socket.emit('stages', message);
    }
  }

});
const shuffle = (array: string[]): string[] => {
  return array.sort(() => Math.random() - 0.5);
};

const initRoom = (): void => {
  playerOne = '';
  playerTwo = '';
  playerOneOption = '';
  playerTwoOption = '';
};
