#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include "Image.h"
#include <math.h>

// This allows you to skip the `std::` in front of C++ standard library
// functions. You can also say `using std::cout` to be more selective.
// You should never do this in a header file.
using namespace std;

int main(int argc, char **argv)
{
	if(argc < 19) {
		cout << "Usage: L01 filename width height x1 y1 r1 g1 b1 x2 y2 r2 g2 b2 x3 y3 r3 g3 b3" << endl;
		return 0;
	}
	// Output filename
	string filename(argv[1]);
	// Width of image
	int width = atoi(argv[2]);
	// Height of image
	int height = atoi(argv[3]);

  // Initialize coordinate variables to make things easier
  float x1 = atoi(argv[4]);
  float y1 = atoi(argv[5]);
  float x2 = atoi(argv[9]);
  float y2 = atoi(argv[10]);
  float x3 = atoi(argv[14]);
  float y3 = atoi(argv[15]);

  // Initialize rgb values again to make things easier
  float r1 = atoi(argv[6]);
  float b1 = atoi(argv[7]);
  float g1 = atoi(argv[8]);
  float r2 = atoi(argv[11]);
  float g2 = atoi(argv[12]);
  float b2 = atoi(argv[13]);
  float r3 = atoi(argv[16]);
  float g3 = atoi(argv[17]);
  float b3 = atoi(argv[18]);

  // Vertex 1
  vertex v1;
  v1.x = x1;
  v1.y = y1;
  v1.z = 0.0;
  v1.r = r1;
  v1.g = g1;
  v1.b = b1;

  // Vertex 2
  vertex v2;
  v2.x = x2;
  v2.y = y2;
  v2.z = 0.0;
  v2.r = r2;
  v2.g = g2;
  v2.b = b2;
  
  // Vertex 3
  vertex v3;
  v3.x = x3;
  v3.y = y3;
  v3.z = 0.0;
  v3.r = r3;
  v3.g = g3;
  v3.b = b3;
  
  // Triangle
  Tri t(v1, v2, v3);

  // Find xmin, xmax, ymin, ymax
  float xmin = x1;
  float xmax = x1;
  float ymin = y1;
  float ymax = y1;
  if(x2 < xmin)
          xmin = x2;
  if(x3 < xmin)
          xmin = x3;
  if(x2 > xmax)
          xmax = x2;
  if(x3 > xmax)
          xmax = x3;
  if(y2 < ymin)
          ymin = y2;
  if(y3 < ymin)
          ymin = y3;
  if(y2 > ymax)
          ymax = y2;
  if(y3 > ymax)
          ymax = y3;

  // Find total area
  float area = abs((x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))/2.0);

	// Create the image. We're using a `shared_ptr`, a C++11 feature.
	auto image = make_shared<Image>(width, height);

  // Initialize variables for holding area between points
	float a1 = 0.0;
  float a2 = 0.0;
  float a3 = 0.0;
  
  // Initialize barycentric coordinate variables
  float l1 = 0.0;
  float l2 = 0.0;
  float l3 = 0.0;
  
  // Draw a rectangle
  for(int y = ymin; y < ymax; ++y) {
		for(int x = xmin; x < xmax; ++x) {
      
      // Find area between point and two other vertices
      a1 = abs(x1 * (y2 - y) + x2 * (y - y1) + x * (y1 - y2))/2.0;
      a2 = abs(x1 * (y - y3) + x * (y3 - y1) + x3 * (y1 - y))/2.0;
      a3 = abs(x * (y2 - y3) + x2 * (y3 - y) + x3 * (y - y2))/2.0;

      // Assign barycentric coordinates
      l1 = a1/area;
      l2 = a2/area;
      l3 = a3/area;

			unsigned char r = (a1*v1.r + a2*v2.r + a3*v3.r)/area;
			unsigned char g = (a1*v1.g + a2*v2.g + a3*v3.g)/area;
			unsigned char b = (a1*v1.b + a2*v2.b + a3*v3.b)/area;

      // Find if point is inside triangle
      //if((l1 <= 0.0 || l1 >= 1.0) || (l2 <= 0.0 || l2 >= 1.0) || (l3 <= 0.0 || l3 >= 1.0))
      if(!(l1 + l2 + l3 <= 1.0001 && l1 + l2 + l3 >= 0.9999))
      {
        continue;
      }
      else
      {
        image->setPixel(x, y, r, g, b);
      }
		}
	}
	// Write image to file
	image->writeToFile(filename);
	return 0;
}
