/**
 * 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();
}
