#pragma region Copyright (c) 2014-2016 OpenRCT2 Developers
/*****************************************************************************
 * OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
 *
 * OpenRCT2 is the work of many authors, a full list can be found in contributors.md
 * For more information, visit https://github.com/OpenRCT2/OpenRCT2
 *
 * OpenRCT2 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 Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * A full copy of the GNU General Public License can be found in licence.txt
 *****************************************************************************/
#pragma endregion

#include "../addresses.h"
#include "../common.h"
#include "../interface/colour.h"
#include "../platform/platform.h"
#include "drawing.h"

/**
 *
 *  rct2: 0x00678AD4
 * dpi (edi)
 * left (ax)
 * top (cx)
 * right (bx)
 * bottom (dx)
 * colour (ebp)
 */
void gfx_fill_rect(rct_drawpixelinfo *dpi, int left, int top, int right, int bottom, int colour)
{
	int left_ = left;
	int right_ = right;
	int top_ = top;
	int bottom_ = bottom;
	rct_drawpixelinfo *dpi_ = dpi;

	if ((left > right) || (top > bottom) || (dpi->x > right) || (left >= (dpi->x + dpi->width)) ||
		(bottom < dpi->y) || (top >= (dpi->y + dpi->height)))
		return;

	colour |= RCT2_GLOBAL(0x009ABD9C, uint32);

	uint16 cross_pattern = 0;

	int start_x = left - dpi->x;
	if (start_x < 0){
		cross_pattern ^= start_x;
		start_x = 0;
	}

	int end_x = right - dpi->x;
	end_x++;
	if (end_x > dpi->width)
		end_x = dpi->width;

	int width = end_x - start_x;

	int start_y = top - dpi->y;
	if (start_y < 0){
		cross_pattern ^= start_y;
		start_y = 0;
	}
	int end_y = bottom - dpi->y;
	end_y++;

	if (end_y > dpi->height)
		end_y = dpi->height;

	int height = end_y - start_y;
	if (colour&0x1000000){
		// 00678B2E    00678BE5
		//Cross hatching
		uint8* dest_pointer = (start_y * (dpi->width + dpi->pitch)) + start_x + dpi->bits;

		uint32 ecx;
		for (int i = 0; i < height; ++i) {
			uint8* next_dest_pointer = dest_pointer + dpi->width + dpi->pitch;
			ecx = cross_pattern;
			// Rotate right
			ecx = (ecx >> 1) | (ecx << (sizeof(ecx) * CHAR_BIT - 1));
			ecx = (ecx & 0xFFFF0000) | width;
			// Fill every other pixel with the colour
			for (; (ecx & 0xFFFF) > 0; ecx--) {
				ecx = ecx ^ 0x80000000;
				if ((int)ecx < 0) {
					*dest_pointer = colour & 0xFF;
				}
				dest_pointer++;
			}
			cross_pattern ^= 1;
			dest_pointer = next_dest_pointer;

		}
		return;
	}
	if (colour & 0x2000000){
		//0x2000000
		// 00678B7E   00678C83
		// Location in screen buffer?
		uint8* dest_pointer = dpi->bits + (uint32)((start_y >> (dpi->zoom_level)) * ((dpi->width >> dpi->zoom_level) + dpi->pitch) + (start_x >> dpi->zoom_level));

		// Find colour in colour table?
		uint16 eax = palette_to_g1_offset[(colour & 0xFF)];
		rct_g1_element g1_element = g1Elements[eax];

		// Fill the rectangle with the colours from the colour table
		for (int i = 0; i < height>>dpi->zoom_level; ++i) {
			uint8* next_dest_pointer = dest_pointer + (dpi->width >> dpi->zoom_level) + dpi->pitch;
			for (int j = 0; j < width>>dpi->zoom_level; ++j) {
				*dest_pointer = g1_element.offset[*dest_pointer];
				dest_pointer++;
			}
			dest_pointer = next_dest_pointer;
		}
		return;
	}
	if (colour & 0x4000000){
		//0x4000000
		// 00678B8A   00678E38
		uint8* dest_pointer = start_y * (dpi->width + dpi->pitch) + start_x + dpi->bits;

		//The pattern loops every 15 lines this is which
		//part the pattern is on.
		int pattern_y = (start_y + dpi->y) % 16;

		//The pattern loops every 15 pixels this is which
		//part the pattern is on.
		int start_pattern_x = (start_x + dpi_->x) % 16;
		int pattern_x = start_pattern_x;

		uint16* pattern_pointer = RCT2_ADDRESS(0x0097FEFC,uint16*)[colour >> 28]; // or possibly uint8)[esi*4] ?

		for (int no_lines = height; no_lines > 0; no_lines--) {
			uint8* next_dest_pointer = dest_pointer + dpi->width + dpi->pitch;
			uint16 pattern = pattern_pointer[pattern_y];

			for (int no_pixels = width; no_pixels > 0; --no_pixels) {
				if (pattern & (1 << pattern_x))
					*dest_pointer = colour & 0xFF;

				pattern_x = (pattern_x + 1) % 16;
				dest_pointer++;
			}
			pattern_x = start_pattern_x;
			pattern_y = (pattern_y + 1) % 16;
			dest_pointer = next_dest_pointer;
		}
		return;
	}
	if (colour & 0x8000000){
		//0x8000000
		// 00678B3A    00678EC9 still to be implemented
		int esi = left - RCT2_GLOBAL(0x1420070,sint16);
		RCT2_GLOBAL(0xEDF824,uint32) = esi;
		esi = top - RCT2_GLOBAL(0x1420072,sint16);
		RCT2_GLOBAL(0xEDF828,uint32) = esi;
		left -= dpi->x;//0x4
		if ( left < 0 ){
			RCT2_GLOBAL(0xEDF824,sint32) -= left;
			left = 0;
		}
		right -= dpi->x;
		right++;
		if ( right > dpi->width ){
			right = dpi->width;
		}
		right -= left;
		top -= dpi->y;
		if ( top < 0 ){
			RCT2_GLOBAL(0xEDF828,sint32) -= top;
			top = 0;
		}
		bottom -= dpi->y;
		bottom++;
		if (bottom > dpi->height){
			bottom = dpi->height;
		}
		bottom -= top;
		RCT2_GLOBAL(0xEDF824,sint32) &= 0x3F;
		RCT2_GLOBAL(0xEDF828,sint32) &= 0x3F;
		esi = dpi->width;
		esi += dpi->pitch;
		esi *= top;
		esi += left;
		esi += (uint32)dpi->bits;
		RCT2_GLOBAL(0xEDF82C,sint32) = right;
		RCT2_GLOBAL(0xEDF830,sint32) = bottom;
		left = dpi->width;
		left+= dpi->pitch;
		left-= right;
		RCT2_GLOBAL(0xEDF834,sint32) = left;
		colour &= 0xFF;
		colour--;
		right = colour;
		colour <<= 8;
		right |= colour;
		RCT2_GLOBAL(0xEDF838,sint32) = right;
		//right <<= 4;
		esi = RCT2_GLOBAL(0xEDF828,sint32);
		esi *= 0x40;
		left = 0;
		esi += (uint32)g1Elements[right].offset;//???
		//Not finished
		//Start of loop
		return;
	}
	//0x0000000
	uint8* dest_pointer = start_y * (dpi->width + dpi->pitch) + start_x + dpi->bits;

	for (int i = 0; i < height; ++i) {
		memset(dest_pointer, (colour & 0xFF), width);
		dest_pointer += dpi->width + dpi->pitch;
	}
}

/**
 * Draw a rectangle, with optional border or fill
 *
 *  rct2: 0x006E6F81
 * dpi (edi)
 * left (ax)
 * top (cx)
 * right (bx)
 * bottom (dx)
 * colour (ebp)
 * flags (si)
 */
void gfx_fill_rect_inset(rct_drawpixelinfo* dpi, short left, short top, short right, short bottom, int colour, short flags)
{
	uint8 shadow, fill, hilight;

	// Flags
	int no_border, no_fill, pressed;

	no_border = 8;
	no_fill = 0x10;
	pressed = 0x20;

	if (colour & 0x180) {
		if (colour & 0x100) {
			colour = colour & 0x7F;
		} else {
			colour = RCT2_ADDRESS(0x009DEDF4,uint8)[colour];
		}

		colour = colour | 0x2000000; //Transparent

		if (flags & no_border) {
			gfx_fill_rect(dpi, left, top, bottom, right, colour);
		} else if (flags & pressed) {
			// Draw outline of box
			gfx_fill_rect(dpi, left, top, left, bottom, colour + 1);
			gfx_fill_rect(dpi, left, top, right, top, colour + 1);
			gfx_fill_rect(dpi, right, top, right, bottom, colour + 2);
			gfx_fill_rect(dpi, left, bottom, right, bottom, colour + 2);

			if (!(flags & no_fill)) {
				gfx_fill_rect(dpi, left+1, top+1, right-1, bottom-1, colour);
			}
		} else {
			// Draw outline of box
			gfx_fill_rect(dpi, left, top, left, bottom, colour + 2);
			gfx_fill_rect(dpi, left, top, right, top, colour + 2);
			gfx_fill_rect(dpi, right, top, right, bottom, colour + 1);
			gfx_fill_rect(dpi, left, bottom, right, bottom, colour + 1);

			if (!(flags & no_fill)) {
				gfx_fill_rect(dpi, left+1, top+1, right-1, bottom-1, colour);
			}
		}
	} else {
		if (flags & 0x80) {
			shadow	= ColourMapA[colour].dark;
			fill	= ColourMapA[colour].mid_light;
			hilight	= ColourMapA[colour].lighter;
		} else {
			shadow	= ColourMapA[colour].mid_dark;
			fill	= ColourMapA[colour].light;
			hilight	= ColourMapA[colour].lighter;
		}

		if (flags & no_border) {
			gfx_fill_rect(dpi, left, top, right, bottom, fill);
		} else if (flags & pressed) {
			// Draw outline of box
			gfx_fill_rect(dpi, left, top, left, bottom, shadow);
			gfx_fill_rect(dpi, left + 1, top, right, top, shadow);
			gfx_fill_rect(dpi, right, top + 1, right, bottom - 1, hilight);
			gfx_fill_rect(dpi, left + 1, bottom, right, bottom, hilight);

			if (!(flags & no_fill)) {
				if (!(flags & 0x40)) {
					if (flags & 0x04) {
						fill = ColourMapA[COLOUR_BLACK].light;
					} else {
						fill = ColourMapA[colour].lighter;
					}
				}
				gfx_fill_rect(dpi, left+1, top+1, right-1, bottom-1, fill);
			}
		} else {
			// Draw outline of box
			gfx_fill_rect(dpi, left, top, left, bottom - 1, hilight);
			gfx_fill_rect(dpi, left + 1, top, right - 1, top, hilight);
			gfx_fill_rect(dpi, right, top, right, bottom - 1, shadow);
			gfx_fill_rect(dpi, left, bottom, right, bottom, shadow);

			if (!(flags & no_fill)) {
				if (flags & 0x04) {
					fill = ColourMapA[COLOUR_BLACK].light;
				}
				gfx_fill_rect(dpi, left+1, top+1, right-1, bottom-1, fill);
			}
		}
	}
}
