/*
 *  Copyright (C) 2008 Tuomas Peippo
 *
 *  This program is distributed under the terms of the
 *  GNU General Public License.
 *
 *  This file is part of Dave the Ordinary Spaceman.
 *
 *  Dave the Ordinary Spaceman 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 3 of the License, or (at your option) any later version.
 *
 *  Dave the Ordinary Spaceman 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 Dave the Ordinary Spaceman. If not, see
 *  <http://www.gnu.org/licenses/>.
 *
 */


#include <SDL/SDL.h>

#ifdef __ON_ISO__
#include <SDL/SDL_main.h>
#include <windows.h>
#endif

#include <fstream>
#include <sstream>
#include <map>
#include "teletext_editor.h"
#include "fellow.h"
#include "analog_effects.h"
#include "ability.h"
#include "model.h"
#include "image.h"
#include "library.h"

using namespace std;

TeletextEditor *teletextEditor;




int main(int argc, char*argv[])
{
  
  char *pic = NULL;
  
  if(argc >= 2)
    pic = argv[1];
  
  teletextEditor = new TeletextEditor(pic);
  return teletextEditor->run();
}

TeletextEditor::TeletextEditor(char * pic) 
{
  //Initialize all SDL subsystems
  if( SDL_Init( SDL_INIT_EVERYTHING ) == -1 ) {
    exit(1);
  }

  width = 800;
  height = 600;

  SDL_SetVideoMode(width, height, 32, SDL_OPENGL | SDL_GL_DOUBLEBUFFER);

  running = true;
 
  if (SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1) == 0)
    cout << "Käytetään vsyncciä\n";

  Uint32 flags = SDL_OPENGL;

  screen = SDL_SetVideoMode(width, height, 32, flags);

  SDL_ShowCursor(SDL_DISABLE);
  
  //glViewport( 0, 0, 512, 512 );

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  
  const float right = 256;
  const float top   = 256;
  glOrtho(0, right, 0, top, -1, 1);
  
  
  glMatrixMode( GL_MODELVIEW );

  /* Reset The View */
  glLoadIdentity( );
  
  
  cursorSize = Vector(256.0f / 40, 256 / 25);


  cursor = Vector(0,0);
  cursorUp = false;
  cursorDown = false;
  cursorLeft = false;
  cursorRight = false;
  showCurrentColor = false;

if(pic)
  bg = lib[pic];
else
  bg = NULL;

#if !defined(__MACOS__) && !defined(__APPLE__)
  glewInit();
#endif

  unsigned int rows = 256 / cursorSize.y;
  
  for(unsigned int i=0;i<rows;i++) {
  
    string fg(40, '1'), bg(40, '9');
    Teletext *temp = new Teletext::Teletext();
    temp->set_color(1.0f,0.0f,0.0f,1.0f);
    
    string empty(40, ' ');
    
    temp->set_position(Vector(0,i*cursorSize.y));
    temp->set_text(empty);
    
    texts.push_back(temp);
    fgColors.push_back(fg);
    bgColors.push_back(bg);
    
  }
  /*
  currentColor.r = 1.0f;
  currentColor.g = 0.0f;
  currentColor.b = 0.0f;
  currentColor.a = 1.0f;
  
  currentBgColor.r = 0.0f;
  currentBgColor.g = 0.0f;
  currentBgColor.b = 1.0f;
  currentBgColor.a = 0.0f;
*/

  currentColor = "1";
  currentBgColor = "9";
  SDL_EnableUNICODE(true);

  colors["0"] = (Color){1.0f,1.0f,1.0f,1.0f};
  colors["1"] = (Color){1.0f,0.0f,0.0f,1.0f};
  colors["2"] = (Color){0.0f,1.0f,0.0f,1.0f};
  colors["3"] = (Color){0.0f,0.0f,1.0f,1.0f};
  colors["4"] = (Color){1.0f,1.0f,0.0f,1.0f};
  colors["5"] = (Color){0.0f,1.0f,1.0f,1.0f};
  colors["6"] = (Color){1.0f,0.0f,1.0f,1.0f};
  colors["7"] = (Color){0.5f,0.5f,0.5f,1.0f};
  colors["8"] = (Color){0.0f,0.0f,0.0f,1.0f};
  colors["9"] = (Color){0.0f,0.0f,0.0f,0.0f};
  

  loadFile("teksti.tv");
/*
  text = new Teletext::Teletext();
  text->set_position(Vector(48,32));
  text->set_text("NÄKÄ nää!");
*/
}

TeletextEditor::~TeletextEditor()
{
}

#warning koodaa muut
static float last_frame_showed_at;

int TeletextEditor::run()
{
  
    while (running) {
    handle();
	render();
      //glFinish();
      SDL_Delay(5);
      //sync();
      SDL_GL_SwapBuffers();
      //SDL_Delay(5);
    }
  SDL_Quit();
  return 0;
}

void TeletextEditor::saveFile(const std::string &name) {
  
  ofstream fileStream(name.c_str(), ios_base::out | ios_base::binary);

  const std::vector<Teletext*> &const_texts = texts;
  std::vector<Teletext*>::const_reverse_iterator iter;
  int i = int(const_texts.size()) - 1;
  for(iter=const_texts.rbegin();iter!=const_texts.rend();iter++,i--){

    cout << i << endl;
    fileStream << (*iter)->get_text() << endl;
    fileStream << fgColors[i] << endl;
    fileStream << bgColors[i] << endl;

    if (i == 10)
      SDL_Delay(500);
  }
  
  fileStream.close();
  
}


void TeletextEditor::loadFile(const std::string &name) {
  
  ifstream fileStream(name.c_str(), ios_base::in | ios_base::binary);

  unsigned int i=texts.size()-1;
  while (fileStream.good()) {
     
     string textLine;
     getline( fileStream, textLine );
     
     string textColorsLine;
     getline( fileStream, textColorsLine );
     
     string bgColorsLine;
     getline( fileStream, bgColorsLine );
     
     
     string::const_iterator textIter;
     for(textIter=textLine.begin();textIter!=textLine.end();textIter++){
       
       Color color;
       Color bgColor;
       
       string charColorStr(1, textColorsLine[(textIter-textLine.begin())]);
       string charStr(1,*(textIter));
       string charBgStr(1,bgColorsLine[(textIter-textLine.begin())]);
       
       color = colors[charColorStr];
       bgColor = colors[charBgStr];
       
       texts[i]->set_bgcolor(bgColor.r, bgColor.g, bgColor.b, bgColor.a);
       texts[i]->set_color(color.r, color.g, color.b, color.a);
       texts[i]->set_char(charStr, (textIter-textLine.begin()));
       
       fgColors[i].replace((textIter-textLine.begin()), 1, charColorStr);
       bgColors[i].replace((textIter-textLine.begin()), 1, charBgStr);
       
     }
     //texts[i]->set_text(textLine);
     
     

     i--; 
   }
     

   fileStream.close();
  
  
}

void TeletextEditor::handleText(SDL_KeyboardEvent key) {
  
  string tmp(1,(char)key.keysym.unicode);
  Uint8 *state = SDL_GetKeyState(NULL);
  bool upper = state[SDLK_LSHIFT] || state[SDLK_RSHIFT];

#if 1
  cerr << "painettiin: " << key.keysym.sym << ", unicodena muka: ";
  for (size_t i=0; i<tmp.size(); i++)
    cerr << '[' << hex << int(tmp[i]) << ']';
  cerr << endl;
#endif
  if (SDLK_F1 <= key.keysym.sym && key.keysym.sym <= SDLK_F11)
    tmp = string(1, char(key.keysym.sym - SDLK_F1 + 20));
  else if (key.keysym.sym == SDLK_RETURN)
    tmp = string(1, char(24));
  else if (key.keysym.sym == SDLK_TAB)
    tmp = string(1, char(21));
  else if (key.keysym.sym == SDLK_WORLD_7 || key.keysym.sym == SDLK_BACKQUOTE)
    tmp = string(1, char(20));
  else if (key.keysym.sym == (SDLKey)91 &&  upper) tmp = string(1, char(0xc5)); //tmp[0] = 0xc3,*/ tmp[0] = 0x85;  // Å
  else if (key.keysym.sym == (SDLKey)39 &&  upper) tmp = string(1, char(0xc4)); //tmp[0] = 0xc3,*/ tmp[0] = 0x84;  // Ä
  else if (key.keysym.sym == (SDLKey)59 &&  upper) tmp = string(1, char(0xd6)); //tmp[0] = 0xc3,*/ tmp[0] = 0x96;  // Ö
  else if (key.keysym.sym == (SDLKey)91 && !upper) tmp = string(1, char(0xe5)); //tmp[0] = 0xc3,*/ tmp[0] = 0xa5;  // å
  else if (key.keysym.sym == (SDLKey)39 && !upper) tmp = string(1, char(0xe4)); //tmp[0] = 0xc3,*/ tmp[0] = 0xa4;  // ä
  else if (key.keysym.sym == (SDLKey)59 && !upper) tmp = string(1, char(0xf6)); //tmp[0] = 0xc3,*/ tmp[0] = 0xb6;  // ö
  else if (!key.keysym.unicode)
    return;

  if (cursor.y < 0.0f || (size_t)(cursor.y/cursorSize.y) >= texts.size())
    return;
  Teletext *curRow = texts[cursor.y/cursorSize.y];
  if(!curRow)
    return;
      
  if(key.keysym.mod & KMOD_ALT && key.keysym.mod & KMOD_SHIFT) {
  
   
    if(key.keysym.sym == SDLK_0) {
  
      // Color color = {1.0f,0.0f,0.0f,0.0f};
      currentColor = "0";
  
      showCurrentColor = true;
  
    } else if (key.keysym.sym == SDLK_1) {
  
      //Color color = {1.0f,0.0f,0.0f,1.0f};
      currentColor = "1";
  
      showCurrentColor = true;

    }  else if (key.keysym.sym == SDLK_2) {
  
      //Color color = {0.0f,1.0f,0.0f,1.0f};
      currentColor = "2";
 
      showCurrentColor = true;

    }  else if (key.keysym.sym == SDLK_3) {

      //Color color = {0.0f,0.0f,1.0f,1.0f};
      currentColor = "3";
 
      showCurrentColor = true;

    }  else if (key.keysym.sym == SDLK_4) {

      //  Color color = {0.0f,0.0f,0.0f,1.0f};
      currentColor = "4";
 
      showCurrentColor = true;


    }  else if (key.keysym.sym == SDLK_5) {
  
      //Color color = {1.0f,1.0f,1.0f,1.0f};
      currentColor = "5";
 
      showCurrentColor = true;


    }  else if (key.keysym.sym == SDLK_6) {
  
      //Color color = {1.0f,1.0f,0.0f,1.0f};
      currentColor = "6";
 
      showCurrentColor = true;


    }  else if (key.keysym.sym == SDLK_7) {

      //Color color = {0.0f,1.0f,1.0f,1.0f};
      currentColor = "7";
 
      showCurrentColor = true;

    }else if (key.keysym.sym == SDLK_8) {
  
      //Color color = {1.0f,0.0f,1.0f,1.0f};
      currentColor = "8";
 
      showCurrentColor = true;
  
  
    }else if (key.keysym.sym == SDLK_9) {
  
      //Color color = {0.5f,0.5f,0.5f,1.0f};
      currentColor = "9";
 
      showCurrentColor = true;
  

    }
    if(timerID){
      SDL_RemoveTimer(timerID);
      timerID=0;
    }
    timerID = SDL_AddTimer(1000, hideCurrentColorBox, NULL);

    return;
  }

  if((key.keysym.mod & KMOD_META) || (key.keysym.mod & KMOD_ALT)) {
  
    if(key.keysym.sym == SDLK_s) {

      saveFile("teksti.tv");

    } else if(key.keysym.sym == SDLK_0) {

      //Color color = {0.0f,0.0f,0.0f,0.0f};
      currentBgColor = "0";

      showCurrentBgColor = true;

    } else if (key.keysym.sym == SDLK_1) {

      //Color color = {1.0f,0.0f,0.0f,1.0f};
      currentBgColor = "1";

      showCurrentBgColor = true;

    }  else if (key.keysym.sym == SDLK_2) {

      // Color color = {0.0f,1.0f,0.0f,1.0f};
      currentBgColor = "2";

      showCurrentBgColor = true;

    }  else if (key.keysym.sym == SDLK_3) {

      //Color color = {0.0f,0.0f,1.0f,1.0f};
      currentBgColor = "3";

      showCurrentBgColor = true;

    }  else if (key.keysym.sym == SDLK_4) {

      //Color color = {0.0f,0.0f,0.0f,1.0f};
      currentBgColor = "4";

      showCurrentBgColor = true;


    }  else if (key.keysym.sym == SDLK_5) {

      //    Color color = {1.0f,1.0f,1.0f,1.0f};
      currentBgColor = "5";

      showCurrentBgColor = true;


    }  else if (key.keysym.sym == SDLK_6) {

      //    Color color = {1.0f,1.0f,0.0f,1.0f};
      currentBgColor = "6";

      showCurrentBgColor = true;


    }  else if (key.keysym.sym == SDLK_7) {

      //Color color = {0.0f,1.0f,1.0f,1.0f};
      currentBgColor = "7";

      showCurrentBgColor = true;

    }else if (key.keysym.sym == SDLK_8) {

      //  Color color = {1.0f,0.0f,1.0f,1.0f};
      currentBgColor = "8";

      showCurrentBgColor = true;


    }else if (key.keysym.sym == SDLK_9) {

      //  Color color = {0.5f,0.5f,0.5f,1.0f};
      currentBgColor = "9";

      showCurrentBgColor = true;


    }
    if(timerID){
      SDL_RemoveTimer(timerID);
      timerID=0;
    }
    timerID = SDL_AddTimer(1000, hideCurrentColorBox, NULL);

    return;
  }
  
  //}

  Color bgColor = colors[currentBgColor];
  Color fgColor = colors[currentColor];
    
  size_t i = (size_t)(cursor.y/cursorSize.y);
  size_t j = (size_t)(round(cursor.x/cursorSize.x));
  if (0 <= i && i < fgColors.size() &&
                i < bgColors.size() &&
    j < fgColors[i].size() &&
    j < bgColors[i].size()) {
    curRow->set_bgcolor(bgColor.r, bgColor.g, bgColor.b, bgColor.a);
    curRow->set_color(fgColor.r, fgColor.g, fgColor.b, fgColor.a);
    curRow->set_char(tmp,j);
    fgColors[i].replace(j, 1, currentColor);
    bgColors[i].replace(j, 1, currentBgColor);
  } else
    cerr << "Editori olis krässänny täs vaihees jos ei sitä olis estetty\n";

  cursor.x += cursorSize.x;
  
}

Uint32 TeletextEditor::hideCurrentColorBox(Uint32 interval, void *param) {
  
  showCurrentColor = false;
  showCurrentBgColor = false;
}

void TeletextEditor::showColor(Color color){
  
  const float w = 256.0f - 20.0f;
  const float h = 5.0f;
  
  glPushMatrix();
  
  glDisable(GL_TEXTURE_2D);

  glTranslatef(10, 10, 0);

  glColor4f(color.r, color.g, color.b, color.a);

  glBegin(GL_QUADS);
  glVertex2f(0.0f, 0.0f);
  glVertex2f(w, 0.0f);
  glVertex2f(w, h);
  glVertex2f(0.0f, h);
  glEnd();
  
  
  glPopMatrix();
  
  
}


void TeletextEditor::handle()
{
  static std::map<SDLKey, std::pair<Uint32, SDL_Event> > pressed_down_at;

  for (std::map<SDLKey, std::pair<Uint32, SDL_Event> >::iterator i=pressed_down_at.begin(); i!=pressed_down_at.end(); ++i)
    if (SDL_GetTicks() - 250 > i->second.first) {
      //i->second.first = SDL_GetTicks() - 250;
      SDL_PushEvent(&i->second.second);
    }

  SDL_Event ev;
  while (SDL_PollEvent(&ev)) {
    switch (ev.type) {

      case SDL_QUIT:
        running = false;
        break;

      case SDL_KEYDOWN:

	if (pressed_down_at.empty())
	  pressed_down_at[ev.key.keysym.sym] = std::pair<Uint32, SDL_Event>(SDL_GetTicks(), ev);
	else
	  if (pressed_down_at.begin()->first != ev.key.keysym.sym) {
	    pressed_down_at.clear();
	    pressed_down_at[ev.key.keysym.sym] = std::pair<Uint32, SDL_Event>(SDL_GetTicks(), ev);
	  }
      
        switch (ev.key.keysym.sym) {
          case SDLK_ESCAPE:
            //running = false;
            break;

          case SDLK_UP:
          //  cursorUp = true;
            cursor.y += cursorSize.y;
            break;

          case SDLK_DOWN:
            //cursorDown = true;
            cursor.y -= cursorSize.y;
            break;

          case SDLK_LEFT:
            //cursorLeft = true;
            cursor.x -= cursorSize.x;
            break;

          case SDLK_RIGHT:
           // cursorRight = true;
            cursor.x += cursorSize.x;
            break;
            
          default:
          handleText(ev.key);
          break;
      }
      break;
      
        case SDL_KEYUP:

	  pressed_down_at.erase(ev.key.keysym.sym);

          switch (ev.key.keysym.sym) {
            
            case SDLK_UP:
              cursorUp = false;
              break;

            case SDLK_DOWN:
              cursorDown = false;
              break;

            case SDLK_LEFT:
              cursorLeft = false;
              break;

            case SDLK_RIGHT:
              cursorRight = false;
              break;
            default:
            break;
            
          }
          break;

    }


  }

  if (cursor.x < 0) cursor.x = 0;
  if (cursor.y < 0) cursor.y = 0;
  if (cursor.x > 39 * cursorSize.x) cursor.x = 39 * cursorSize.x;
  if (cursor.y > 24 * cursorSize.y) cursor.y = 24 * cursorSize.y;


if (cursorUp) {
  cursor.y += cursorSize.y;
}

if (cursorDown) {
  cursor.y -= cursorSize.y;
}

if (cursorLeft) {
  cursor.x -= cursorSize.x;
}

if (cursorRight) {
  cursor.x += cursorSize.x;
}
  


  
}
void TeletextEditor::drawText() {
 
  std::vector<Teletext*>::iterator iter;
  
  for(iter=texts.begin();iter != texts.end(); iter++ ) {
    (*iter)->render();
    
  } 
  
}

void TeletextEditor::drawCursor() {
  


    glPushMatrix();
    
    glDisable(GL_TEXTURE_2D);


    glTranslatef(cursor.x, cursor.y, 0);


    glColor4f(0.0f, 1.0f, 0.0f, 0.5f);

    glBegin(GL_QUADS);
    glVertex2f(0.0f, 0.0f);
    glVertex2f(cursorSize.x, 0.0f);
    glVertex2f(cursorSize.x, cursorSize.y);
    glVertex2f(0.0f, cursorSize.y);
    glEnd();
    
    
    glPopMatrix();
}

void TeletextEditor::drawBg() {
  


    glPushMatrix();
    
    glEnable(GL_TEXTURE_2D);

    bg->bind();


    glColor4f(1.0f, 1.0f, 1.0f, 0.3f);
 
    
      glBegin(GL_QUADS);
      glTexCoord2f(0.0f, 1.0f); 
      glVertex2f(0.0f, 0.0f);
      glTexCoord2f(1.0f, 1.0f); 
      glVertex2f(256, 0.0f);
      glTexCoord2f(1.0f, 0.0f); 
      glVertex2f(256, 256);
      glTexCoord2f(0.0f, 0.0f);
      glVertex2f(0.0f, 256);
      glEnd();
    
    
    glPopMatrix();
}



void TeletextEditor::render()
{

/*
  glDisable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);
  glDisable(GL_LIGHTING);
  glDisable(GL_ALPHA_TEST);
  glDisable(GL_COLOR_MATERIAL);
  glDisable(GL_STENCIL_TEST);
*/
  //glEnable(GL_TEXTURE_2D);


//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

  
 // glMatrixMode( GL_MODELVIEW );
   //   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//	glLoadIdentity();

 //glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

 // glMatrixMode(GL_MODELVIEW);
  //glLoadIdentity();
  
 



  //glDisable(GL_BLEND);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

if(bg)
  drawBg();

//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

drawText();
 
drawCursor();



if(showCurrentColor){
    Color fgColor = colors[currentColor];
  showColor(fgColor);
}
if(showCurrentBgColor){
    Color bgColor = colors[currentBgColor];
  showColor(bgColor);
}
  //glScalef(0.1f, 0.1f, 1.0f);
  
 
}


