/**
 * projectM -- Milkdrop-esque visualisation SDK
 * Copyright (C)2003-2004 projectM Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * See 'LICENSE.txt' included within this release
 *
 */

#include <cstdio>
#include <cstring>
#include <cstdlib>

#ifdef WIN32
#include "win32-dirent.h"
#else
#include <dirent.h>
#endif /** WIN32 */
#include <time.h>

#include "MilkdropPreset.hpp"
#include "Parser.hpp"
#include "ParamUtils.hpp"
#include "InitCondUtils.hpp"
#include "fatal.h"
#include <iostream>
#include <fstream>

#include "PresetFrameIO.hpp"

MilkdropPreset::MilkdropPreset(std::istream & in, const std::string & presetName,  PresetOutputs & presetOutputs):
	Preset(presetName),
    	builtinParams(_presetInputs, presetOutputs),
    	_presetOutputs(presetOutputs)
{
  initialize(in);

}

MilkdropPreset::MilkdropPreset(const std::string & absoluteFilePath, const std::string & presetName, PresetOutputs & presetOutputs):
	Preset(presetName),
    builtinParams(_presetInputs, presetOutputs),
    _absoluteFilePath(absoluteFilePath),
    _presetOutputs(presetOutputs),
    _filename(parseFilename(absoluteFilePath))
{

  initialize(absoluteFilePath);

}
MilkdropPreset::~MilkdropPreset()
{

  traverse<TraverseFunctors::Delete<InitCond> >(init_cond_tree);

  traverse<TraverseFunctors::Delete<InitCond> >(per_frame_init_eqn_tree);

  traverse<TraverseFunctors::Delete<PerPixelEqn> >(per_pixel_eqn_tree);

  traverseVector<TraverseFunctors::Delete<PerFrameEqn> >(per_frame_eqn_tree);

  traverse<TraverseFunctors::Delete<Param> >(user_param_tree);

  /// Testing deletion of render items by the preset. would be nice if it worked, 
  /// and seems to be working if you use a mutex on the preset switching.
  
  for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); 
	pos != customWaves.end(); ++pos ) {
  //  __android_log_print(ANDROID_LOG_ERROR, "projectM", "not freeing wave %x", *pos);
    delete(*pos);
  }

  for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); 
	pos != customShapes.end(); ++pos ) {
//__android_log_print(ANDROID_LOG_ERROR, "projectM", "not freeing shape %x", *pos);

	delete(*pos);
  }
  customWaves.clear();
 customShapes.clear();
 presetOutputs().customWaves.clear();
 presetOutputs().customShapes.clear();
  presetOutputs().drawables.clear();

}

/* Adds a per pixel equation according to its string name. This
   will be used only by the parser */

int MilkdropPreset::add_per_pixel_eqn(char * name, GenExpr * gen_expr)
{

  PerPixelEqn * per_pixel_eqn = NULL;
  int index;
  Param * param = NULL;

  assert(gen_expr);
  assert(name);

  if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: per pixel equation (name = \"%s\")\n", name);

  /* Search for the parameter so we know what matrix the per pixel equation is referencing */

  param = ParamUtils::find(name, &this->builtinParams, &this->user_param_tree);
  if ( !param )
  {
    if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to allocate a new parameter!\n");
    return PROJECTM_FAILURE;
  }

  index = per_pixel_eqn_tree.size();

  /* Create the per pixel equation given the index, parameter, and general expression */
  if ((per_pixel_eqn = new PerPixelEqn(index, param, gen_expr)) == NULL)
  {
    if (PER_PIXEL_EQN_DEBUG) printf("add_per_pixel_eqn: failed to create new per pixel equation!\n");
    return PROJECTM_FAILURE;
  }



  /* Insert the per pixel equation into the preset per pixel database */
  std::pair<std::map<int, PerPixelEqn*>::iterator, bool> inserteeOption = per_pixel_eqn_tree.insert
      (std::make_pair(per_pixel_eqn->index, per_pixel_eqn));

  if (!inserteeOption.second)
  {
    printf("failed to add per pixel eqn!\n");
    delete(per_pixel_eqn);
    return PROJECTM_FAILURE;
  }

  /* Done */
  return PROJECTM_SUCCESS;
}

void MilkdropPreset::evalCustomShapeInitConditions()
{

  for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos) {
    assert(*pos);
    (*pos)->evalInitConds();
  }
}


void MilkdropPreset::evalCustomWaveInitConditions()
{

  for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos) {
    assert(*pos);
   (*pos)->evalInitConds();
}
}


void MilkdropPreset::evalCustomWavePerFrameEquations()
{

  for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
  {

    std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
    for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
    {
      assert(_pos->second);
      _pos->second->evaluate();
    }

    std::vector<PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
    for (std::vector<PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
    {
      (*_pos)->evaluate();
    }
  }

}

void MilkdropPreset::evalCustomShapePerFrameEquations()
{

  for (PresetOutputs::cshape_container::iterator pos = customShapes.begin(); pos != customShapes.end(); ++pos)
  {

    std::map<std::string, InitCond*> & init_cond_tree = (*pos)->init_cond_tree;
    for (std::map<std::string, InitCond*>::iterator _pos = init_cond_tree.begin(); _pos != init_cond_tree.end(); ++_pos)
    {
      assert(_pos->second);
      _pos->second->evaluate();
    }

    std::vector<PerFrameEqn*> & per_frame_eqn_tree = (*pos)->per_frame_eqn_tree;
    for (std::vector<PerFrameEqn*>::iterator _pos = per_frame_eqn_tree.begin(); _pos != per_frame_eqn_tree.end(); ++_pos)
    {
      (*_pos)->evaluate();
    }
  }

}

void MilkdropPreset::evalPerFrameInitEquations()
{

  for (std::map<std::string, InitCond*>::iterator pos = per_frame_init_eqn_tree.begin(); pos != per_frame_init_eqn_tree.end(); ++pos)
  {
    assert(pos->second);
    pos->second->evaluate();
  }

}

void MilkdropPreset::evalPerFrameEquations()
{

  for (std::map<std::string, InitCond*>::iterator pos = init_cond_tree.begin(); pos != init_cond_tree.end(); ++pos)
  {
    assert(pos->second);
    pos->second->evaluate();
  }

  for (std::vector<PerFrameEqn*>::iterator pos = per_frame_eqn_tree.begin(); pos != per_frame_eqn_tree.end(); ++pos)
  {
    (*pos)->evaluate();
  }

}

void MilkdropPreset::preloadInitialize() {

  /// @note commented this out because it should be unnecessary
  // Clear equation trees
  //init_cond_tree.clear();
  //user_param_tree.clear();
  //per_frame_eqn_tree.clear();
  //per_pixel_eqn_tree.clear();
  //per_frame_init_eqn_tree.clear();


}

void MilkdropPreset::postloadInitialize() {

  /* It's kind of ugly to reset these values here. Should definitely be placed in the parser somewhere */
  this->per_frame_eqn_count = 0;
  this->per_frame_init_eqn_count = 0;

  this->loadBuiltinParamsUnspecInitConds();
  this->loadCustomWaveUnspecInitConds();
  this->loadCustomShapeUnspecInitConds();


/// @bug are you handling all the q variables conditions? in particular, the un-init case?
//m_presetOutputs.q1 = 0;
//m_presetOutputs.q2 = 0;
//m_presetOutputs.q3 = 0;
//m_presetOutputs.q4 = 0;
//m_presetOutputs.q5 = 0;
//m_presetOutputs.q6 = 0;
//m_presetOutputs.q7 = 0;
//m_presetOutputs.q8 = 0;

}

void MilkdropPreset::Render(const BeatDetect &music, const PipelineContext &context)
{
	_presetInputs.update(music, context);

	evaluateFrame();
	pipeline().Render(music, context);

}

void MilkdropPreset::initialize(const std::string & pathname)
{
  int retval;

  preloadInitialize();

if (MILKDROP_PRESET_DEBUG)
  std::cerr << "[Preset] loading file \"" << pathname << "\"..." << std::endl;

  if ((retval = loadPresetFile(pathname)) < 0)
  {
if (MILKDROP_PRESET_DEBUG)
     std::cerr << "[Preset] failed to load file \"" <<
      pathname << "\"!" << std::endl;

    /// @bug how should we handle this problem? a well define exception?
    throw retval;
  }

  postloadInitialize();
}

void MilkdropPreset::initialize(std::istream & in)
{
  int retval;

  preloadInitialize();

  if ((retval = readIn(in)) < 0)
  {

	if (MILKDROP_PRESET_DEBUG)
     std::cerr << "[Preset] failed to load from stream " << std::endl;

    /// @bug how should we handle this problem? a well define exception?
    throw retval;
  }

  postloadInitialize();
}

void MilkdropPreset::loadBuiltinParamsUnspecInitConds() {

  InitCondUtils::LoadUnspecInitCond loadUnspecInitCond(this->init_cond_tree, this->per_frame_init_eqn_tree);

  this->builtinParams.apply(loadUnspecInitCond);
  traverse(user_param_tree, loadUnspecInitCond);

}

void MilkdropPreset::loadCustomWaveUnspecInitConds()
{

  for (PresetOutputs::cwave_container::iterator pos = customWaves.begin(); pos != customWaves.end(); ++pos)
  {
    assert(*pos);
    (*pos)->loadUnspecInitConds();
  }

}

void MilkdropPreset::loadCustomShapeUnspecInitConds()
{

  for (PresetOutputs::cshape_container::iterator pos = customShapes.begin();
	pos != customShapes.end(); ++pos)
  {
    assert(*pos);
    (*pos)->loadUnspecInitConds();
  }
}


void MilkdropPreset::evaluateFrame()
{

  // Evaluate all equation objects according to milkdrop flow diagram

  evalPerFrameInitEquations();
  evalPerFrameEquations();

  // Important step to ensure custom shapes and waves don't stamp on the q variable values
  // calculated by the per frame (init) and per pixel equations.
  transfer_q_variables(customWaves);
  transfer_q_variables(customShapes);

  initialize_PerPixelMeshes();

  evalPerPixelEqns();

  evalCustomWaveInitConditions();
  evalCustomWavePerFrameEquations();

  evalCustomShapeInitConditions();
  evalCustomShapePerFrameEquations();

  // Setup pointers of the custom waves and shapes to the preset outputs instance
  /// @slow an extra O(N) per frame, could do this during eval
  _presetOutputs.customWaves = PresetOutputs::cwave_container(customWaves);
  _presetOutputs.customShapes = PresetOutputs::cshape_container(customShapes);

}

void MilkdropPreset::initialize_PerPixelMeshes()
{

  int x,y;
      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.cx_mesh[x][y]=presetOutputs().cx;
	}}




      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.cy_mesh[x][y]=presetOutputs().cy;
	}}



      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.sx_mesh[x][y]=presetOutputs().sx;
	}}




      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.sy_mesh[x][y]=presetOutputs().sy;
	}}



      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.dx_mesh[x][y]=presetOutputs().dx;
	}}

//std::cout<<presetOutputs().cx<<","<<presetOutputs().cy<<" "<<presetOutputs().dx<<","<<presetOutputs().dy<<std::endl;

      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.dy_mesh[x][y]=presetOutputs().dy;
	}}



      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.zoom_mesh[x][y]=presetOutputs().zoom;
	}}




      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.zoomexp_mesh[x][y]=presetOutputs().zoomexp;
	}}



      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.rot_mesh[x][y]=presetOutputs().rot;
	}}


      for (x=0;x<presetInputs().gx;x++){
	for(y=0;y<presetInputs().gy;y++){
	  _presetOutputs.warp_mesh[x][y]=presetOutputs().warp;
	}}



}
// Evaluates all per-pixel equations
void MilkdropPreset::evalPerPixelEqns()
{

  /* Evaluate all per pixel equations in the tree datastructure */
  for (int mesh_x = 0; mesh_x < presetInputs().gx; mesh_x++)
	  for (int mesh_y = 0; mesh_y < presetInputs().gy; mesh_y++)
  for (std::map<int, PerPixelEqn*>::iterator pos = per_pixel_eqn_tree.begin();
       pos != per_pixel_eqn_tree.end(); ++pos)
    pos->second->evaluate(mesh_x, mesh_y);

}

int MilkdropPreset::readIn(std::istream & fs) {

  line_mode_t line_mode;
  presetOutputs().compositeShader.programSource.clear();
  presetOutputs().warpShader.programSource.clear();

  /* Parse any comments */
  if (Parser::parse_top_comment(fs) < 0)
  {
	if (MILKDROP_PRESET_DEBUG)
    		std::cerr << "[Preset::readIn] no left bracket found..." << std::endl;
    return PROJECTM_FAILURE;
  }

  /* Parse the preset name and a left bracket */
  char tmp_name[MAX_TOKEN_SIZE];

  if (Parser::parse_preset_name(fs, tmp_name) < 0)
  {
    std::cerr <<  "[Preset::readIn] loading of preset name failed" << std::endl;
    return PROJECTM_ERROR;
  }

  /// @note  We ignore the preset name because [preset00] is just not so useful

  // Loop through each line in file, trying to successfully parse the file.
  // If a line does not parse correctly, keep trucking along to next line.
  int retval;
  while ((retval = Parser::parse_line(fs, this)) != EOF)
  {
    if (retval == PROJECTM_PARSE_ERROR)
    {
      line_mode = UNSET_LINE_MODE;
      // std::cerr << "[Preset::readIn()] parse error in file \"" << this->absoluteFilePath() << "\"" << std::endl;
    }
  }

//  std::cerr << "loadPresetFile: finished line parsing successfully" << std::endl;

  /* Now the preset has been loaded.
     Evaluation calls can be made at appropiate
     times in the frame loop */

return PROJECTM_SUCCESS;
}

/* loadPresetFile: private function that loads a specific preset denoted
   by the given pathname */
int MilkdropPreset::loadPresetFile(const std::string & pathname)
{


  /* Open the file corresponding to pathname */
  std::ifstream fs(pathname.c_str());
  if (!fs || fs.eof()) {
    if (MILKDROP_PRESET_DEBUG)
    	std::cerr << "loadPresetFile: loading of file \"" << pathname << "\" failed!\n";
    return PROJECTM_ERROR;
  }

 return readIn(fs);

}

const std::string & MilkdropPreset::name() const {
	
	return name().empty() ? filename() : name();
}

