/*
 * Robot.cpp
 *
 *  Created on: Dec 31, 2010
 *      Author: cpresser
 */

#include "Robot.h"

#include <iostream>

using namespace std;

int Robot::sNextID = 0;
Random Robot::sRand;

Robot::Robot(Ogre::SceneManager* sceneMgr):
                mWalkSpeed(35.0f), mId(sNextID++)
{
        //create the robot
        // Create the entity
        stringstream sstr;
        sstr << "Robot" << mId;
        mName = sstr.str();
        string nodeName = mName + "_Node";

        mEntity = sceneMgr->createEntity(mName, "robot.mesh");

        float x = sRand.nextInt(-100, 500);
        float y = 0.0f;
        float z = sRand.nextInt(-200, 200);

        // Create the scene node
        mNode = sceneMgr->getRootSceneNode()->
                        createChildSceneNode(nodeName, Ogre::Vector3(x, y, z));
        mNode->attachObject(mEntity);

        //create a path of 3 nodes for it (random)
        for(int i = 1; i <= 4; i++){

                mWalkList.push_back(Ogre::Vector3(x,  y,  z ));

                Ogre::Entity *ent;
                Ogre::SceneNode *node;

                stringstream knotStream;
                knotStream << mName << "_" << i;
                string knotName = knotStream.str();

                //add knots underneath each point?
                ent = sceneMgr->createEntity(knotName, "knot.mesh");
                node = sceneMgr->getRootSceneNode()->createChildSceneNode(knotName + "Node",
                                Ogre::Vector3(x, -10.0f,  z));
                node->attachObject(ent);
                node->setScale(0.1f, 0.1f, 0.1f);

                x = sRand.nextInt(-100, 500);
                //y = 0.0f;
                z = sRand.nextInt(-200, 200);
        }


}

Robot::~Robot() {
        // TODO Auto-generated destructor stub
}

void Robot::update(const Ogre::FrameEvent &evt){

        if (!mIsWalking)
        {
                //is there somewhere else to walk?
                if (nextLocation())
                {
                        // Set walking animation
                        mAnimationState = mEntity->getAnimationState("Walk");
                        mAnimationState->setLoop(true);
                        mAnimationState->setEnabled(true);
                }
        }
        else
        {
                Ogre::Real move = mWalkSpeed * evt.timeSinceLastFrame;
                mDistance -= move;

                //are we there yet?
                if (mDistance <= 0.0f)
                {
                        mNode->setPosition(mDestination);
                        mDirection = Ogre::Vector3::ZERO;
                        mIsWalking = false;
                        // Set animation based on if the robot has another point to walk to.
                        if (! nextLocation())
                        {
                                //no particular place to go
                                // Set Idle animation
                                //mAnimationState = mEntity->getAnimationState("Idle");
                                mAnimationState = mEntity->getAnimationState("Die");
                                mAnimationState->setLoop(false);
                                mAnimationState->setEnabled(true);
                        }
                        else
                        {
                                // Rotation Code
                                Ogre::Vector3 src = mNode->getOrientation() * Ogre::Vector3::UNIT_X;
                                if ((1.0f + src.dotProduct(mDirection)) < 0.0001f)
                                {
                                        //avoid divide by zero caused by 180 rotation
                                        mNode->yaw(Ogre::Degree(180));
                                }
                                else
                                {
                                        Ogre::Quaternion quat = src.getRotationTo(mDirection);
                                        mNode->rotate(quat);
                                } // else
                        }
                }
                else
                {
                        mNode->translate(mDirection * move);
                } // else
        } // if
        mAnimationState->addTime(evt.timeSinceLastFrame);
}


void Robot::setupAnimation(){
        // Set idle animation
        mAnimationState = mEntity->getAnimationState("Idle");
        mAnimationState->setLoop(true);
        mAnimationState->setEnabled(true);

        // Set default values for variables
        mWalkSpeed = 35.0f;
        mDirection = Ogre::Vector3::ZERO;
        mIsWalking = false;
}

bool Robot::nextLocation(void){
        if (mWalkList.empty())
                return false;

        mDestination = mWalkList.front();  // this gets the front of the deque
        mWalkList.pop_front();             // this removes the front of the deque

        mDirection = mDestination - mNode->getPosition();
        mDistance = mDirection.normalise();
        mIsWalking = true;

        return true;
}

int Robot::getId(){
        return mId;
}

string Robot::getName(){
        return mName;
}