/*
QuickCG 20191227

Copyright (c) 2004-2019, Lode Vandevenne

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
QuickCG is an SDL 1.2 codebase that wraps some of the SDL 1.2 functionality.
It's used by Lode's Computer Graphics Tutorial to work with simple function calls
to demonstrate graphical programs. It may or may not be of industrial strength
for games, though I've actually used it for some.

QuickCG can handle some things that standard C++ does not but that are useful, such as:
-drawing graphics
-a bitmap font
-simplified saving and loading of files
-reading keyboard and mouse input
-playing sound
-color models
-loading images

Contact info:
My email address is (puzzle the account and domain together with an @ symbol):
Domain: gmail dot com.
Account: lode dot vandevenne.
*/

#ifndef _quickcg_h_included
#define _quickcg_h_included

#include <SDL2/SDL.h>
#include <string>
#include <sstream>
#include <iomanip>
#include <vector>
#include <algorithm> //std::min and std::max

namespace QuickCG
{

  ////////////////////////////////////////////////////////////////////////////////
  // useful templates//////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////

  // don't know why, but the standard C++ abs sometimes gives cryptic errors? if so use this :D
  template <typename T>
  const T template_abs(const T &a)
  {
    return (a < 0) ? -a : a;
  }

  // usage: std::string str = valtostr(25454.91654654f);
  template <typename T>
  std::string valtostr(const T &val)
  {
    std::ostringstream sstream;
    sstream << val;
    return sstream.str();
  }

  // usage: double val = strtoval<double>("465498.654");
  template <typename T>
  T strtoval(const std::string &s)
  {
    std::istringstream sstream(s);
    T val;
    sstream >> val;
    return val;
  }

  // length is decimal precision of the floating point number
  template <typename T>
  std::string valtostr(const T &val, int length, bool fixed = true)
  {
    std::ostringstream sstream;
    if (fixed)
      sstream << std::fixed;
    sstream << std::setprecision(length) << val;
    return sstream.str();
  }

  ////////////////////////////////////////////////////////////////////////////////
  // COLOR STRUCTS/////////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////

  struct ColorRGB8bit;
  // a color with 3 components: r, g and b
  struct ColorRGB
  {
    int r;
    int g;
    int b;

    ColorRGB(Uint8 r, Uint8 g, Uint8 b);
    ColorRGB(const ColorRGB8bit &color);
    ColorRGB();
  };

  ColorRGB operator+(const ColorRGB &color, const ColorRGB &color2);
  ColorRGB operator-(const ColorRGB &color, const ColorRGB &color2);
  ColorRGB operator*(const ColorRGB &color, int a);
  ColorRGB operator*(int a, const ColorRGB &color);
  ColorRGB operator/(const ColorRGB &color, int a);
  bool operator==(const ColorRGB &color, const ColorRGB &color2);
  bool operator!=(const ColorRGB &color, const ColorRGB &color2);

  static const ColorRGB RGB_Black(0, 0, 0);
  static const ColorRGB RGB_Red(255, 0, 0);
  static const ColorRGB RGB_Green(0, 255, 0);
  static const ColorRGB RGB_Blue(0, 0, 255);
  static const ColorRGB RGB_Cyan(0, 255, 255);
  static const ColorRGB RGB_Magenta(255, 0, 255);
  static const ColorRGB RGB_Yellow(255, 255, 0);
  static const ColorRGB RGB_White(255, 255, 255);
  static const ColorRGB RGB_Gray(128, 128, 128);
  static const ColorRGB RGB_Grey(192, 192, 192);
  static const ColorRGB RGB_Maroon(128, 0, 0);
  static const ColorRGB RGB_Darkgreen(0, 128, 0);
  static const ColorRGB RGB_Navy(0, 0, 128);
  static const ColorRGB RGB_Teal(0, 128, 128);
  static const ColorRGB RGB_Purple(128, 0, 128);
  static const ColorRGB RGB_Olive(128, 128, 0);

  // a color with 3 components: r, g and b
  struct ColorRGB8bit
  {
    Uint8 r;
    Uint8 g;
    Uint8 b;

    ColorRGB8bit(Uint8 r, Uint8 g, Uint8 b);
    ColorRGB8bit(const ColorRGB &color);
    ColorRGB8bit();
  };

  // a color with 3 components: h, s and l
  struct ColorHSL
  {
    int h;
    int s;
    int l;

    ColorHSL(Uint8 h, Uint8 s, Uint8 l);
    ColorHSL();
  };

  // a color with 3 components: h, s and v
  struct ColorHSV
  {
    int h;
    int s;
    int v;

    ColorHSV(Uint8 h, Uint8 s, Uint8 v);
    ColorHSV();
  };

  ////////////////////////////////////////////////////////////////////////////////
  // COLOR CONVERSIONS/////////////////////////////////////////////////////////////
  ////////////////////////////////////////////////////////////////////////////////
  ColorHSL RGBtoHSL(const ColorRGB &colorRGB);
  ColorRGB HSLtoRGB(const ColorHSL &colorHSL);
  ColorHSV RGBtoHSV(const ColorRGB &colorRGB);
  ColorRGB HSVtoRGB(const ColorHSV &colorHSV);
  Uint32 RGBtoINT(const ColorRGB &colorRGB);
  ColorRGB INTtoRGB(Uint32 colorINT);

}

#endif