#include "abstractfactory.h"
#include "units/unit.h"
#include "cell.h"
#include "effects/effect.h"

#include <iostream>
#include <algorithm>
#include <cassert>
#include <string>

#include <QFile>
#include <QString>
#include <QTextStream>
#include <QSettings>
#include <QDebug>

Unit::Unit(QString parameters) {
    QStringList params = parameters.split("|");

    assert(params.size() >= 2);

    race_id_ = params[0];
    unit_id_ = params[1];

    QString unit_folder = ":/assets/units/" + race_id_ + "/" + unit_id_ + "/";

    loadUnitName(unit_folder);
    loadUnitDescr(unit_folder);
    loadUnitBaseClass(unit_folder);
    loadUnitTraits(unit_folder);
    loadUnitIcon(unit_folder);
    loadUnitPrevSpecs(unit_folder);
    loadUnitUpgradeSpecs(unit_folder);
}

void Unit::loadUnitName(QString unit_folder) {
    QFile file(unit_folder + "unitname.txt");
    file.open(QIODevice::ReadOnly);
    QTextStream in(&file);
    in.setCodec("UTF-8");
    unit_name_ = in.readLine();
}

void Unit::loadUnitDescr(QString unit_folder) {
    QFile file(unit_folder + "descr.txt");
    file.open(QIODevice::ReadOnly);
    QTextStream in(&file);
    in.setCodec("UTF-8");
    unit_descr_ = in.readAll();
}

void Unit::loadUnitBaseClass(QString unit_folder) {
    QFile file(unit_folder + "baseclass.txt");
    file.open(QIODevice::ReadOnly);
    QTextStream in(&file);
    in.setCodec("UTF-8");
    base_class_id_ = in.readLine();
}

void Unit::loadUnitTraits(QString unit_folder) {
    QSettings traits(unit_folder + "traits.ini", QSettings::IniFormat);
    level_ = traits.value("lvl", -1).toInt();
    cost_ = traits.value("cost", -1).toInt();
    starting_activity_points_ = traits.value("starting_ap", -1).toInt();
    strength_ = traits.value("strength", -1).toInt();
    agility_ = traits.value("agility", -1).toInt();
    initiative_ = traits.value("initiative", -1).toInt();
    magic_defence_ = traits.value("magic_def", -1).toInt();
    physic_defence_ = traits.value("physic_def", -1).toInt();
}

void Unit::loadUnitIcon(QString unit_folder) {
    unit_icon_.load(unit_folder + "icon.png");
}

void Unit::loadUnitPrevSpecs(QString unit_folder) {
    QFile file(unit_folder + "prevgrades.txt");
    file.open(QIODevice::ReadOnly);
    QTextStream in(&file);
    in.setCodec("UTF-8");
    QString line = in.readLine();
    while (!in.atEnd()) {
        parent_specs_.push_back(line);
        line = in.readLine();
    }
    parent_specs_.push_back(line);
    line = in.readLine();

}

void Unit::loadUnitUpgradeSpecs(QString unit_folder) {
    QFile file(unit_folder + "nextgrades.txt");
    file.open(QIODevice::ReadOnly);
    QTextStream in(&file);
    in.setCodec("UTF-8");
    QString line = in.readLine();
    while (!in.atEnd()) {
        upgrade_specs_.push_back(line);
        line = in.readLine();
    }
    upgrade_specs_.push_back(line);
    line = in.readLine();
}

int Unit::getCost(){
	return cost_;
}

std::vector<QString> Unit::getParentSpecs(){
    return parent_specs_;
}

std::vector<QString> Unit::getUpgradeSpecs(){
	return upgrade_specs_;
}

double Unit::getExperience() {
	return experience_;
}

int Unit::getLevel() {
	return level_;
}

int Unit::getHealthPoints() {
	return health_points_;
}

int Unit::getActivityPoints(){
	return activity_points_;
}

int Unit::getStartingActivityPoints() {
	return starting_activity_points_;
}

Cell* Unit::getLocation() {
	return location_;
}

void Unit::setLocation(Cell* to) {
	location_ = to;
}

int Unit::getMaxHealthPoints(){
 	return max_health_points_;  
}
  	
void Unit::setHealthPoints(int value){
	health_points_ = value;
}

int Unit::getInitiative() {
	return initiative_;
}

int Unit::getIntelligence() {
	return intelligence_;
}

int Unit::getStrength() {
	return strength_;
}

int Unit::getAgility() {
	return agility_;
}

int Unit::getMagicDefence() {
	return magic_defence_;
}

int Unit::getPhysicDefence() {
	return physic_defence_;
}

double Unit::getRealX() {
	return real_x_;
}

void Unit::setRealX(double x) {
	real_x_ = x;
}

double Unit::getRealY() {
	return real_y_;
}

void Unit::setRealY(double y) {
	real_y_ = y;
}

bool Unit::isCharacter(){
    return true;
}

QString Unit::getUnitId() const {
    return unit_id_;
}

QString Unit::getUnitName() const {
    return unit_name_;
}

QString Unit::getUnitDescr() const {
    return unit_descr_;
}

QString Unit::getUnitBaseClassId() const {
    return base_class_id_;
}

QImage Unit::getUnitIcon() const {
    return unit_icon_;
}

void Unit::operateEffectList(){
    for(std::vector<Effect*>::iterator it = beginIteratorEffectsList();
            it != endIteratorEffectsList(); ++it){
        (*it)->OperateOnUnit(this);
    }
}
void Unit::add(Effect* effect){
    if(effect == nullptr)
        throw new std::string("Try to add undefined effect to unit");
    effects_.push_back(effect);
}
void Unit::remove(std::vector<Effect*>::iterator it){
    if(beginIteratorEffectsList() <= it && it < endIteratorEffectsList()){
        effects_.erase(it);
    }
}
void Unit::remove(Effect* effect){
    for(std::vector<Effect*>::iterator it = beginIteratorEffectsList();
            it != endIteratorEffectsList(); ++it){
        if((*it) == effect){
            remove(it);
            return;
        }
    }
}
std::vector<Effect*>::iterator Unit::beginIteratorEffectsList(){
    return effects_.begin();
}
std::vector<Effect*>::iterator Unit::endIteratorEffectsList(){
    return effects_.end();
}

