/*
 * Copyright 2007-2008 Thomas Gallinari <tg8187@yahoo.fr>
 *
 * This program 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 2 of
 * the License, or (at your option) any later version.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "kapman.h"

#include <KgDifficulty>

const qreal Kapman::MAX_SPEED_RATIO = 1.5;

Kapman::Kapman(qreal p_x, qreal p_y, Maze *p_maze) : Character(p_x, p_y, p_maze)
{
    m_type = Element::KAPMAN;
    m_maxSpeed = m_normalSpeed * MAX_SPEED_RATIO;
}

Kapman::~Kapman()
{

}

void Kapman::init()
{
    goRight();
    updateDirection();
    // Stop animation
    emit(stopped());
}

void Kapman::goUp()
{
    m_askedXSpeed = 0;
    m_askedYSpeed = -m_speed;
}

void Kapman::goDown()
{
    m_askedXSpeed = 0;
    m_askedYSpeed = m_speed;
}

void Kapman::goRight()
{
    m_askedXSpeed = m_speed;
    m_askedYSpeed = 0;
}

void Kapman::goLeft()
{
    m_askedXSpeed = -m_speed;
    m_askedYSpeed = 0;
}

void Kapman::updateDirection()
{
    setXSpeed(m_askedXSpeed);
    setYSpeed(m_askedYSpeed);
    m_askedXSpeed = 0;
    m_askedYSpeed = 0;
    // Signal to the kapman item that the direction changed
    emit(directionChanged());
}

void Kapman::updateMove()
{
    // If the kapman does not move
    if (m_xSpeed == 0 && m_ySpeed == 0) {
        // If the user asks for moving
        if (m_askedXSpeed != 0 || m_askedYSpeed != 0) {
            // Check the next cell with the asked direction
            if (getAskedNextCell().getType() == Cell::CORRIDOR) {
                // Update the direction
                updateDirection();
                // Move the kapman
                move();
            }
        }
    }
    // If the kapman is already moving
    else {
        // If the kapman wants to go back it does not wait to be on a center
        if ((m_xSpeed != 0 && m_askedXSpeed == -m_xSpeed) || (m_ySpeed != 0 && m_askedYSpeed == -m_ySpeed)) {
            // Go back
            updateDirection();
            // If the kapman just turned at a corner and instantly makes a half-turn, do not run into a wall
            if (isOnCenter() && getNextCell().getType() != Cell::CORRIDOR) {
                // Stop moving
                stopMoving();
            } else {
                // Move the kapman
                move();
            }
        } else {
            // If the kapman gets on a cell center
            if (onCenter()) {
                // If there is an asked direction (not a half-turn) and the corresponding next cell is accessible
                if ((m_askedXSpeed != 0 || m_askedYSpeed != 0)
                    && (m_askedXSpeed != m_xSpeed || m_askedYSpeed != m_ySpeed)
                    && (getAskedNextCell().getType() == Cell::CORRIDOR)) {
                    // Move the kapman on the cell center
                    moveOnCenter();
                    // Update the direction
                    updateDirection();
                } else {
                    // Check the next cell with the kapman current direction
                    if (getNextCell().getType() != Cell::CORRIDOR) {
                        // Move the kapman on the cell center
                        moveOnCenter();
                        // Stop moving
                        stopMoving();
                    } else {
                        // Move the kapman
                        move();
                    }
                }
            } else {
                // Move the kapman
                move();
            }
        }
    }
}

void Kapman::winPoints(Element *p_element)
{
    // Emits a signal to the game
    emit(sWinPoints(p_element));
}

void Kapman::die()
{
    emit(eaten());
}

void Kapman::emitGameUpdated()
{
    emit(gameUpdated());
}

qreal Kapman::getAskedXSpeed() const
{
    return m_askedXSpeed;
}

qreal Kapman::getAskedYSpeed() const
{
    return m_askedYSpeed;
}

Cell Kapman::getAskedNextCell()
{
    // Get the current cell coordinates from the character coordinates
    int curCellRow = m_maze->getRowFromY(m_y);
    int curCellCol = m_maze->getColFromX(m_x);
    Cell nextCell;

    // Get the next cell function of the character asked direction
    if (m_askedXSpeed > 0) {
        nextCell = m_maze->getCell(curCellRow, curCellCol + 1);
    } else if (m_askedXSpeed < 0) {
        nextCell = m_maze->getCell(curCellRow, curCellCol - 1);
    } else if (m_askedYSpeed > 0) {
        nextCell = m_maze->getCell(curCellRow + 1, curCellCol);
    } else if (m_askedYSpeed < 0) {
        nextCell = m_maze->getCell(curCellRow - 1, curCellCol);
    }

    return nextCell;
}

void Kapman::stopMoving()
{
    setXSpeed(0);
    setYSpeed(0);
    m_askedXSpeed = 0;
    m_askedYSpeed = 0;
    emit(stopped());
}

void Kapman::initSpeedInc()
{
    // Kapman speed increase when level up
    switch ((int) Kg::difficultyLevel()) {
    case KgDifficultyLevel::Easy:
        m_speedIncrease = Character::LOW_SPEED_INC / 2;
        break;
    case KgDifficultyLevel::Medium:
        m_speedIncrease = Character::MEDIUM_SPEED_INC / 2;
        break;
    case KgDifficultyLevel::Hard:
        m_speedIncrease = Character::HIGH_SPEED_INC / 2;
        break;
    }
}
