/*  RetroArch - A frontend for libretro.
 *  Copyright (C) 2010-2017 - Hans-Kristian Arntzen
 * 
 *  RetroArch 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 Found-
 *  ation, either version 3 of the License, or (at your option) any later version.
 *
 *  RetroArch 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 RetroArch.
 *  If not, see <http://www.gnu.org/licenses/>.
 */

#include "slang_preprocess.h"
#include "glslang_util.hpp"
#include <vector>
#include <string>
#include <algorithm>
#include "../../verbosity.h"
#include "../../libretro-common/include/compat/strl.h"

using namespace std;

bool slang_preprocess_parse_parameters(const char *shader_path,
      struct video_shader *shader)
{
   glslang_meta meta;
   vector<string> lines;
   if (!glslang_read_shader_file(shader_path, &lines, true))
      return false;

   if (!glslang_parse_meta(lines, &meta))
      return false;

   unsigned old_num_parameters = shader->num_parameters;

   // Assumes num_parameters is initialized to something sane.
   for (auto &param : meta.parameters)
   {
      bool mismatch_dup = false;
      bool dup = false;

      auto itr = find_if(shader->parameters, shader->parameters + shader->num_parameters,
         [&](const video_shader_parameter &parsed_param) {
            return param.id == parsed_param.id;
         });

      if (itr != shader->parameters + shader->num_parameters)
      {
         dup = true;
         // Allow duplicate #pragma parameter, but only if they are exactly the same.
         if (param.desc != itr->desc ||
             param.initial != itr->initial ||
             param.minimum != itr->minimum ||
             param.maximum != itr->maximum ||
             param.step != itr->step)
         {
            RARCH_ERR("[Vulkan]: Duplicate parameters found for \"%s\", but arguments do not match.\n",
                  itr->id);
            mismatch_dup = true;
         }
      }

      if (dup && !mismatch_dup)
         continue;

      if (mismatch_dup || shader->num_parameters == GFX_MAX_PARAMETERS)
      {
         shader->num_parameters = old_num_parameters;
         return false;
      }

      auto &p = shader->parameters[shader->num_parameters++];
      strlcpy(p.id, param.id.c_str(), sizeof(p.id));
      strlcpy(p.desc, param.desc.c_str(), sizeof(p.desc));
      p.initial = param.initial;
      p.minimum = param.minimum;
      p.maximum = param.maximum;
      p.step = param.step;
      p.current = param.initial;
   }

   return true;
}

