// File:   sim.cpp
// Date:   1 Apr 2005
// Author: Goldwasser
//
// This file serves as a driver for the Ball Simulation programming
// assignment.
//
// It can be compiled with the associated Makefile by typing 'make' 
// which results in an executable named 'sim'


#include <iostream>
#include <string>
#include <cstdlib>
#include "ball.h"
#include "world.h"


class Controller {

public:
  Controller() {
    W = NULL;
  }


  ~Controller() { if (W) delete W; }      

  void StartDialog() {
    CreateWorld();
    CreateBalls();
    cout << "Goodbye" << endl;
  }

private:
  // Let's set up some convenient default values
  static const float DEFAULT_WIDTH = 12.0;
  static const float DEFAULT_HEIGHT = 10.0;
  static const float DEFAULT_DELAY = 0.2;
  static const float DEFAULT_GRAV = 0.005;
  static const float DEFAULT_STARMASS = 0.1;
  bool extra;

  World* W;


  float ReadFloat(float def) {
    char temp[101];
    cin.getline(temp,100);
    char* end;
    float f = strtof(temp,&end);
    if (end == temp) {
      f = def;
    }
    return f;
  }

  int ReadInt(int def) {
    char temp[101];
    cin.getline(temp,100);
    char* end;
    int i = strtol(temp,&end,10);
    if (end == temp) {
      i = def;
    }
    return i;
  }

  bool ReadYN(bool def) {
    bool result = def;
    char c;
    string temp;
    getline(cin,temp);

    if (temp.length()>0) {
      if (temp[0] == (def ? 'n' : 'y') ||
	  temp[0] == (def ? 'N' : 'Y'))
	result = !result;
    }
    return result;
  }



  void CreateWorld() {
    cout << "Welcome to our simulator." << endl
	 << "Throughout this program, we will offer default responses" << endl
	 << "with each question.  If you wish to accept the default," << endl
	 << "you may simply enter return.   Now let's begin." << endl << endl;

    cout << "First, we must set the dimension of our world." << endl;
    cout << "What width would you like? (default: " << DEFAULT_WIDTH << ") : ";
    float width = ReadFloat(DEFAULT_WIDTH);

    cout << "What height would you like? (default: " << DEFAULT_HEIGHT << ") : ";
    float height = ReadFloat(DEFAULT_HEIGHT);


    cout << endl << "Next we must decide what type of world." << endl
	 << "The standard world has uniform, vertical gravity." << endl
	 << "An extra credit world has gravity based upon a star." << endl;

    cout << endl << "Would you like the extra credit version? (default: n) : ";
    extra = ReadYN(false);

    float grav;
    if (extra) {
      cout << "What mass does the star have? (default: " << DEFAULT_STARMASS << ") : ";
      grav = ReadFloat(DEFAULT_STARMASS);
    } else {
      cout << "What gravity value would you like? (default: " << DEFAULT_GRAV << ") : ";
      grav = ReadFloat(DEFAULT_GRAV);
    }

    cout << "What animation delay would you like? (default: " << DEFAULT_DELAY << " sec) : ";
    float delay = ReadFloat(DEFAULT_DELAY);

    if (extra) {
      W = new World(width,height,width/2.0,height/2.0, grav);
    } else {
      W = new World(width,height,grav);
    }


    W->SetDelay(delay);

    cout << "The world has been successfully created." << endl;
  }

  void CreateBalls() {

    float ix,iy,ivx,ivy;
    bool done = false;

    while (!done) {

      cout << endl << "Would you like to add a ball? (default: y) : ";
      done = !ReadYN(true);
      if (done) break;

      ix = (extra ? 0.5 : 0.25)*W->GetWidth();
      cout << "Enter X coordinate of initial position (default: " << ix << ") : ";
      ix = ReadFloat(ix);

      iy = 0.8*W->GetHeight();
      cout << "Enter Y coordinate of initial position (default: " << iy << ") : ";
      iy = ReadFloat(iy);

      ivx = (extra ? 0.125 : 0.1);
      cout << "Enter X coordinate of initial velocity (default: " << ivx << ") : ";
      ivx = ReadFloat(ivx);

      ivy = (extra ? 0.0 : -0.25);
      cout << "Enter Y coordinate of initial velocity (default: " << ivy << ") : ";
      ivy = ReadFloat(ivy);

      Ball* b = new Ball();
      b->SetPositionX(ix);
      b->SetPositionY(iy);
      b->SetVelocityX(ivx);
      b->SetVelocityY(ivy);

      W->AddBall(*b);
    }
  }

};



int ApiMain() {

  Controller C;
  C.StartDialog();

}
