//
//  Piece.cpp
//  prog2
//
//  Created by Neil Killeen on 5/9/13.
//  Copyright (c) 2013 Neil Killeen. All rights reserved.
//

#include "Piece.h"

Piece::Piece(PieceType type, Grid* curr_grid) {
    grid = curr_grid;
    piece_speed = 500;
    current_pos = grid->getStartPos();
    switch (type) {
        case PIECE_I:
            localcoords.push_back(point3(0,0,0));
            localcoords.push_back(point3(0,1,0));
            localcoords.push_back(point3(0,-1,0));
            localcoords.push_back(point3(0,-2,0));
            color = color4(0.0, 0.0, 1.0, 1.0);
            break;
        case PIECE_L:
            localcoords.push_back(point3(0,0,0));
            localcoords.push_back(point3(0,1,0));
            localcoords.push_back(point3(0,-1,0));
            localcoords.push_back(point3(1,-1,0));
            color = color4(0.0, 1.0, 0.0, 1.0);
            break;
        case PIECE_O:
            localcoords.push_back(point3(0,0,0));
            localcoords.push_back(point3(0,1,0));
            localcoords.push_back(point3(1,0,0));
            localcoords.push_back(point3(1,1,0));
            color = color4(1.0, 0.0, 0.0, 1.0);
            break;
        case PIECE_S:
            localcoords.push_back(point3(-1,1,0));
            localcoords.push_back(point3(-1,0,0));
            localcoords.push_back(point3(0,0,0));
            localcoords.push_back(point3(0,-1,0));
            color = color4(1.0, 1.0, 0.0, 1.0);
            break;
        case PIECE_T:
            localcoords.push_back(point3(-1,0,0));
            localcoords.push_back(point3(0,0,0));
            localcoords.push_back(point3(1,0,0));
            localcoords.push_back(point3(0,-1,0));
            color = color4(0.0, 1.0, 1.0, 1.0);
            break;
            
        default:
            break;
    }
    
    for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor)
        grid->setNode(*itor + current_pos, color);
}

void Piece::Rotate(GLfloat x, GLfloat y, GLfloat z) {
    vector<point3> tmp_localcoords;
    
    // Change get new local coords
    for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor) {
        vec4 tmpvec = RotateX(x) * RotateY(y) * RotateZ(z) * vec4(*itor,1.0);
        tmp_localcoords.push_back(vec3(round(tmpvec.x), round(tmpvec.y), round(tmpvec.z)));
    }
    
    // Set the old cubes to empty
    for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor)
        grid->setNode(*itor + current_pos, color4(), false);

    // Check if there is a block, if so, get out.
    for (auto itor = tmp_localcoords.begin(); itor != tmp_localcoords.end(); ++itor)
        if (!grid->InBounds(current_pos + *itor) || grid->getElement(current_pos + *itor)->filled) {
            // Set the old cubes to filled
            for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor)
                grid->setNode(*itor + current_pos, color, true);
            return;
        }
    
    // Set the new cubes to filled
    localcoords = tmp_localcoords;
    for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor)
        grid->setNode(*itor + current_pos, color, true);
}

bool Piece::Translate(GLfloat x, GLfloat y, GLfloat z) {
    vec3 new_pos = current_pos;
    new_pos.x += x;
    new_pos.y += y;
    new_pos.z += z;
    
    // Set the old cubes to empty
    for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor)
        grid->setNode(*itor + current_pos, color4(), false);

    // Check if there is a block, if so, get out.
    for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor) 
        if (!grid->InBounds(new_pos + *itor) || grid->getElement(new_pos + *itor)->filled) {
            // Set the old cubes to filled
            for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor)
                grid->setNode(*itor + current_pos, color, true);
            return false;
        }
    
    // Set the new cubes to filled
    current_pos = new_pos;
    for (auto itor = localcoords.begin(); itor != localcoords.end(); ++itor)
        grid->setNode(*itor + current_pos, color, true);
    
    return true;
}