# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render
from gameAPI.models import gameSession, gameHistory

#REST API
from rest_framework import generics, status, viewsets
from rest_framework.views import APIView
from rest_framework.response import Response
#RESPONSE
from django.http import HttpResponseRedirect, HttpResponse, JsonResponse


import random
import string
import simplejson as json
from datetime import datetime, timedelta
from battleshipCore import Ship, GamePlayer, Ocean

class getGameSessionView(APIView):
    def get(self, request):
        gameSession_qs = gameSession.objects.filter(session_state='start')
        for session in gameSession_qs:
            print session.session_id
        context = {
            'success': True
        }
        return Response(context, status=status.HTTP_200_OK)


class createGameSessionView(APIView):
    def session_random(self):
        return ''.join(random.choice(string.ascii_letters) for x in range(10))
    
    def get(self, request):
        self.session_key = self.session_random()
        battleship = GamePlayer(self.session_key)
        gameSession_qs = gameSession.objects.filter(session_id=self.session_key)
        if not gameSession_qs:
            newGameSessionCreate = gameSession.objects.create(session_id=self.session_key, create_date=datetime.now(), session_state='start')
            newGameSessionCreate.save()

            game_board_context = {
                "state": "start",
                "game_parameter": {"hit": 0, "miss": 0, "action": "start new game."},
                "ship": {
                    "battleship":{"size": 4,"count": 1, "hp": 0},
                    "cruisers":{"size":3,"count":2, "hp": 0},
                    "destroyers":{"size":2,"count":3, "hp": 0},
                    "submarines":{"size":1,"count":4, "hp": 0}
                },
                "board": battleship.getGameBoard()
            }
            newBoardGameCreate = gameHistory.objects.create(session_id=newGameSessionCreate, game_board=json.dumps(game_board_context))
            newBoardGameCreate.save()
        context = {
            'success': True,
            'session': self.session_key,
        }
        # return HttpResponseRedirect("/api/session/"+self.session_key+"/board/")
        return Response(context, status=status.HTTP_200_OK)

class gamePlayingSessionView(generics.ListAPIView):
    def get(self, request, request_parameter):
        context = {}
        self.user_timezone = 7
        argument_  = request_parameter.split('/')
        if len(argument_) == 1:
            try:
                gameSession_qs = gameSession.objects.get(session_id=argument_[0])
                responseStatus = status.HTTP_200_OK
                context = {
                    'success'   : True,
                    'session'   : gameSession_qs.session_id,
                    'state'     : gameSession_qs.session_state,
                    'create'    : (gameSession_qs.create_date+timedelta(hours=self.user_timezone)).strftime('%Y-%m-%d %H:%M:%S')
                }
                return Response(context, status=responseStatus)
            except Exception as e:
                context = {
                        'success': False,
                        'message': 'session not found'
                    }
                return Response(context, status=status.HTTP_400_BAD_REQUEST)
        elif len(argument_) == 2:
            if str(argument_[1]).lower() == 'board':
                try:
                    gameSession_qs  = gameSession.objects.get(session_id=argument_[0])
                    if gameSession_qs:
                        if gameSession_qs.session_state != 'end':
                            gameBoard_qs    = gameHistory.objects.filter(session_id=gameSession_qs.id).latest('id')
                            if gameBoard_qs:
                                responseStatus  = status.HTTP_200_OK
                                context = {
                                    'success'   : True,
                                    'session'   : gameSession_qs.session_id,
                                    'state'     : gameSession_qs.session_state,
                                    'update'    : (history.registerTime+timedelta(hours=self.user_timezone)).strftime('%Y-%m-%d %H:%M:%S'),
                                    'game'      : json.loads(gameBoard_qs.game_board)
                                }
                        else:
                            responseStatus  = status.HTTP_200_OK
                            context = {
                                'success'   : True,
                                'session'   : gameSession_qs.session_id,
                                'state'     : gameSession_qs.session_state,
                                'create'    : (gameSession_qs.create_date+timedelta(hours=self.user_timezone)).strftime('%Y-%m-%d %H:%M:%S')
                            }
                        return Response(context, status=responseStatus)
                except Exception as e:
                    context = {
                            'success': False,
                            'message': 'session not found'
                        }
                    return Response(context, status=status.HTTP_400_BAD_REQUEST)
            elif str(argument_[1]).lower() == 'history':
                try:
                    game_history_response = []
                    gameSession_qs  = gameSession.objects.get(session_id=argument_[0])
                    gameBoard_qs    = gameHistory.objects.filter(session_id=gameSession_qs.id)
                    for history in gameBoard_qs:
                        game_history_dict = {}
                        game_history_json = json.loads(history.game_board)
                        game_history_dict['datetime'] = (history.registerTime+timedelta(hours=self.user_timezone)).strftime('%Y-%m-%d %H:%M:%S')
                        game_history_dict['action'] = game_history_json['game_parameter']['action']
                        game_history_response.append(game_history_dict)
                    context = {
                        'success': True,
                        'history': game_history_response
                    }
                    return Response(context, status=status.HTTP_200_OK)
                except Exception as e:
                    print str(e)
                    context = {
                        'success': False,
                        'message': 'session not found'
                    }
                    return Response(context, status=status.HTTP_400_BAD_REQUEST)
                
        context = {
            'success': False,
            'message': 'action not found'
        }
        return Response(context, status=status.HTTP_400_BAD_REQUEST)
    
    def post(self, request, request_parameter):
        request_ok = False
        request_status = status.HTTP_400_BAD_REQUEST
        argument_  = request_parameter.split('/')
        action_data = request.body
        action_data_json = json.loads(action_data)

        if len(argument_) == 2:
            if argument_[1].lower() == 'action':
                gameSession_qs  = gameSession.objects.get(session_id=argument_[0])
                gameBoard_qs    = gameHistory.objects.filter(session_id=gameSession_qs.id).latest('id')

                action_type = str(action_data_json['action']).lower()
                game_user_data = json.loads(gameBoard_qs.game_board)

                game_ocean_board = Ocean(10, False)
                game_ocean_board.setBoard(game_user_data['board'])

                if action_type == 'putship':
                    if game_user_data['state'] == 'start':
                        try:
                            ship_type = action_data_json['ship']
                            ship_size = game_user_data['ship'][ship_type]['size']
                            ship_count = game_user_data['ship'][ship_type]['count']
                            ship_position_col = action_data_json['position'][0]
                            ship_position_row = action_data_json['position'][1]
                            ship_rotation = True if action_data_json['rotation'] == "true" else False
                            if ship_count > 0:
                                if game_ocean_board.putShip(Ship(ship_type.upper(), ship_size, ship_count), ship_position_col, ship_position_row, ship_rotation):
                                    game_user_data['ship'][ship_type]['count'] -= 1
                                    game_user_data['board'] = game_ocean_board.getBoard()
                                    ship_available = game_user_data['ship']['battleship']['count']
                                    ship_available += game_user_data['ship']['cruisers']['count']
                                    ship_available += game_user_data['ship']['destroyers']['count']
                                    ship_available += game_user_data['ship']['submarines']['count']
                                    
                                    game_user_data['game_parameter']['action'] = "put "+str(ship_type)+' to [COL:'+str(action_data_json['position'][0])+'][ROW:'+str(action_data_json['position'][1])+']'
                                    historyBoardGameCreate = gameHistory.objects.create(session_id=gameSession_qs, game_board=json.dumps(game_user_data))
                                    historyBoardGameCreate.save()

                                    if ship_available == 0:
                                        game_user_data['game_parameter']['action'] = 'all ship ready.'
                                        game_user_data['state'] = 'playing'
                                        gameSession_qs.session_state = 'playing'
                                        historyBoardGameCreate = gameHistory.objects.create(session_id=gameSession_qs, game_board=json.dumps(game_user_data))
                                        historyBoardGameCreate.save()
                                        gameSession_qs.save()
                                    
                                    game_ocean_board.Print()
                                    context = {
                                        'success': True,
                                        'game': game_user_data
                                    }
                                    return Response(context, status=status.HTTP_200_OK)
                                else:
                                    context = {
                                        'success': False,
                                        'message': 'Invalid position'
                                    }
                                    return Response(context, status=request_status)
                            else:
                                context = {
                                    'success': False,
                                    'message': 'ship is not available'
                                }
                                return Response(context, status=request_status)
                        except Exception as e:
                            print str(e)
                            context = {
                                'success': False,
                                'message': 'ship type error [battleship, cruisers, destroyers, submarines]'
                            }
                            return Response(context, status=request_status)
                    elif game_user_data['state'] == 'end':
                        context = {
                            'success': False,
                            'message': 'the game is over'
                        }
                        return Response(context, status=request_status)
                    
                    else:
                        context = {
                            'success': False,
                            'message': 'you already put all of ship on the ocean'
                        }
                        return Response(context, status=request_status)

                elif action_type == 'shoot':
                    if game_user_data['state'] == 'playing':
                        response_message = 'Hit'
                        ship_dead = []
                        gameSession_qs  = gameSession.objects.get(session_id=argument_[0])
                        gameBoard_qs    = gameHistory.objects.filter(session_id=gameSession_qs.id).latest('id')

                        action_type = str(action_data_json['action']).lower()
                        game_user_data = json.loads(gameBoard_qs.game_board)

                        game_ocean_board = Ocean(10, False)
                        game_ocean_board.setBoard(game_user_data['board'])

                        action_position_col = action_data_json['position'][0]
                        action_position_row = action_data_json['position'][1]

                        if action_position_col > 9 or action_position_row > 9:
                            context = {
                                'success': False,
                                'message': 'Invalid position'
                            }
                            return Response(context, status=status.HTTP_400_BAD_REQUEST)
                        
                        battleship_available_pre    = game_user_data['ship']['battleship']['hp']    / game_user_data['ship']['battleship']['size']
                        cruisers_available_pre      = game_user_data['ship']['cruisers']['hp']      / game_user_data['ship']['cruisers']['size']
                        destroyers_available_pre    = game_user_data['ship']['destroyers']['hp']    / game_user_data['ship']['destroyers']['size']
                        submarines_available_pre    = game_user_data['ship']['submarines']['hp']    / game_user_data['ship']['submarines']['size']

                        attack = game_ocean_board.checkDropPosition(action_position_col, action_position_row)
                        game_user_data['game_parameter']['action'] = 'shoot at [COL:'+str(action_position_col)+'][ROW:'+str(action_position_row)+']'
                        if attack == 'X':
                            game_user_data['game_parameter']['miss'] += 1
                            response_message = 'Miss'
                        elif attack == 'O':
                            context = {
                                'success': False,
                                'message': 'this position is already shot'
                            }
                            return Response(context, status=status.HTTP_400_BAD_REQUEST)
                        elif attack == 'B':
                             game_user_data['game_parameter']['hit']    += 1
                             game_user_data['ship']['battleship']['hp'] += 1
                        elif attack == 'C':
                            game_user_data['game_parameter']['hit']     += 1
                            game_user_data['ship']['cruisers']['hp']    += 1
                        elif attack == 'D':
                            game_user_data['game_parameter']['hit']     += 1
                            game_user_data['ship']['destroyers']['hp']  += 1
                        elif attack == 'S':
                            game_user_data['game_parameter']['hit']     += 1
                            game_user_data['ship']['submarines']['hp']  += 1
                        
                        battleship_available    = game_user_data['ship']['battleship']['hp']    / game_user_data['ship']['battleship']['size']
                        cruisers_available      = game_user_data['ship']['cruisers']['hp']      / game_user_data['ship']['cruisers']['size']
                        destroyers_available    = game_user_data['ship']['destroyers']['hp']    / game_user_data['ship']['destroyers']['size']
                        submarines_available    = game_user_data['ship']['submarines']['hp']    / game_user_data['ship']['submarines']['size']

                        if battleship_available != battleship_available_pre:
                            response_message += ' battleship!'
                        if cruisers_available != cruisers_available_pre:
                            response_message += ' cruisers!'
                        if destroyers_available != destroyers_available_pre:
                            response_message += ' destroyers!'
                        if submarines_available != submarines_available_pre:
                            response_message += ' submarines!'

                        for battleship in range(0, battleship_available):
                            ship_dead.append('battleship')
                        for cruisers in range(0, cruisers_available):
                            ship_dead.append('cruisers')
                        for destroyers in range(0, destroyers_available):
                            ship_dead.append('destroyers')
                        for submarines in range(0, submarines_available):
                            ship_dead.append('submarines')
                        
                        game_ocean_board.Print()
                        print game_ocean_board.shipOnOcean()
                        if game_ocean_board.shipOnOcean() == 0:
                            user_move_count = 0
                            game_user_data['game_parameter']['action'] += ' and game is over!'
                            game_user_data['state'] = 'end'
                            gameSession_qs.session_state = 'end'
                            gameSession_qs.save()

                            historyBoardGameCreate = gameHistory.objects.create(session_id=gameSession_qs, game_board=json.dumps(game_user_data))
                            historyBoardGameCreate.save()

                            game_session_summary = gameHistory.objects.filter(session_id=gameSession_qs.id).latest('id')
                            game_session_summary_parameter = json.loads(game_session_summary.game_board)
                            user_move_count = game_session_summary_parameter['game_parameter']['miss'] + game_session_summary_parameter['game_parameter']['hit']
                            context = {
                                'success': True,
                                'message': 'Win ! You completed the game in ' + str(user_move_count) + \
                                ' moves and miss: ' +str(game_session_summary_parameter['game_parameter']['miss']) + \
                                ' shots, hit:'+str(game_session_summary_parameter['game_parameter']['hit'])+' shots'
                            }
                            return Response(context, status=request_status)
                        
                        historyBoardGameCreate = gameHistory.objects.create(session_id=gameSession_qs, game_board=json.dumps(game_user_data))
                        historyBoardGameCreate.save()

                        context = {
                            'success': True,
                            'message': response_message,
                            'ship': ship_dead
                        }
                        return Response(context, status=request_status)
                    elif game_user_data['state'] == 'end':
                        context = {
                            'success': True,
                            'message': 'game is end'
                        }
                        return Response(context, status=request_status)
                    else:
                        context = {
                            'success': True,
                            'message': 'game not ready put ship first.'
                        }
                        return Response(context, status=request_status)
        context = {
            'success': False,
            'message': 'action error'
        }
        return Response(context, status=request_status)