precision mediump float;
#define LOWPREC lowp
// Uniforms look like they're shared between vertex and fragment shaders in GLSL, so we have to be careful to avoid name clashes

uniform sampler2D gm_BaseTexture;

uniform bool gm_PS_FogEnabled;
uniform vec4 gm_FogColour;
uniform bool gm_AlphaTestEnabled;
uniform float gm_AlphaRefValue;

void DoAlphaTest(vec4 SrcColour)
{
	if (gm_AlphaTestEnabled)
	{
		if (SrcColour.a <= gm_AlphaRefValue)
		{
			discard;
		}
	}
}

void DoFog(inout vec4 SrcColour, float fogval)
{
	if (gm_PS_FogEnabled)
	{
		SrcColour = mix(SrcColour, gm_FogColour, clamp(fogval, 0.0, 1.0)); 
	}
}

#define _YY_GLSLES_ 1
precision highp float;

//
//  shColorReplaceBlendExt
//
//      Replaces multiple colors with others. Can replace 
//      similar colors while preserving shading.
//
//      colorIn             color to replace (vec4)
//      colorOut            replacement color (vec4)
//      colorTolerance      HSVA tolerances (vec4)
//      blend               1.0 preserves shading of original, 
//                          0.0 replaces color as-is (float)
//
//  GMLscripts.com
//
varying vec2 v_vTexcoord;
varying vec4 v_vColour;
varying vec3 v_vPosition;

const int maxcolors = 9;

uniform vec4  colorIn[maxcolors];
uniform vec4  colorOut[maxcolors];
uniform vec4  colorTolerance[maxcolors];
uniform vec4  blend[maxcolors];

uniform float effectY;
uniform float playerX;
uniform float playerY;
uniform int   special;
uniform float time;
// 1 - American Wrastor
// 2 - Genesis Forsburn (moved to separate shader)
// 3 - Excaliburn
// 4 - Champ Kragg
// 5 - Pool Party Ranno

vec3 rgb_to_hsv(vec3 col)
{
    float H = 0.0;
    float S = 0.0;
    float V = 0.0;
    
    float M = max(col.r, max(col.g, col.b));
    float m = min(col.r, min(col.g, col.b));
    
    V = M;
    
    float C = M - m;
    
    if (C > 0.0)
    {
        if (M == col.r) H = mod( (col.g - col.b) / C, 6.0);
        if (M == col.g) H = (col.b - col.r) / C + 2.0;
        if (M == col.b) H = (col.r - col.g) / C + 4.0;
        H /= 6.0;
        S = C / V;
    }
    
    return vec3(H, S, V);
}

vec3 hsv_to_rgb(vec3 col)
{
    float H = col.r;
    float S = col.g;
    float V = col.b;
    
    float C = V * S;
    
    H *= 6.0;
    float X = C * (1.0 - abs( mod(H, 2.0) - 1.0 ));
    float m = V - C;
    C += m;
    X += m;
    
    if (H < 1.0) return vec3(C, X, m);
    if (H < 2.0) return vec3(X, C, m);
    if (H < 3.0) return vec3(m, C, X);
    if (H < 4.0) return vec3(m, X, C);
    if (H < 5.0) return vec3(X, m, C);
    else         return vec3(C, m, X);
}

void main()
{
    vec4 colorPixel = texture2D( gm_BaseTexture, v_vTexcoord );
    
    vec4 colorResult = colorPixel;
    
    vec4 colorHSV = vec4( rgb_to_hsv( colorPixel.rgb ), colorPixel.a);
    
    
    for (int i=0; i< maxcolors; i+=1)
    {            
        vec4 colorInHSV = vec4( rgb_to_hsv( colorIn[i].rgb ), colorIn[i].a);
        
        vec4 colorDelta = colorHSV - colorInHSV;
        
        if (abs(colorDelta.r)>0.5) colorDelta.r -= sign(colorDelta.r);
    
        if ( all( lessThanEqual( abs(colorDelta), colorTolerance[i] ) ) ) 
        {
            vec4 tColorOut = colorOut[i];
			if (special == 7){ //SnS Orcane
				if (i < 3){
					//float t_y = floor((playerY - v_vPosition.y) * 0.5) * 2.0;
					//float t_x = floor((playerX - v_vPosition.x) * 0.5) * 2.0;
					float t_y = floor((v_vPosition.y) * 0.5) * 2.0;
					float t_x = floor((playerX - v_vPosition.x) * 0.5) * 2.0;
					if (t_y > effectY + 4.0*sin((t_x - floor(time*0.5))*0.2)){
						tColorOut.r = 1.0;
                        tColorOut.g = 181.0/255.0;
                        tColorOut.b = 65.0/255.0;
					}
				}
			} else if (special == 9){ //Dreamscape Fors
				if (i == 5){
					float fade = clamp((playerY - v_vPosition.y)/effectY, 0.0, 1.0); //0 at bottom, 1 at top
					float denom = .00392; // 1.0 / 255.0
					float r1 = 150.0*denom;
					float g1 = 14.0*denom;
					float b1 = 166.0*denom;
					float r2 = 24.0*denom;
					float g2 = 4.0*denom;
					float b2 = 76.0*denom;
					float t_x = floor((playerX - v_vPosition.x) * 0.5);
		            float t_y = floor((playerY - v_vPosition.y) * 0.5);
		            float modx1 = mod(t_x - floor(time*0.01),8.0);
		            float mody1 = mod(t_y - floor(time*0.01),8.0);
					float isStar1 = float(((modx1 == 0.0 && mody1 == 0.0) || (modx1 == 4.0 && mody1 == 4.0)) && playerX != -800.0);
					float shine_value1 = 0.5 + 0.5 * sin(t_y + floor(time*0.04)) * cos(t_x + floor(time*0.02));
					float modx2 = mod(t_x + floor(time*0.01),5.0);
		            float mody2 = mod(t_y + floor(time*0.01),5.0);
					float isStar2 = float(((modx2 == 1.0 && mody2 == 2.0) || (modx2 == 3.0 && mody2 == 0.0)) && playerX != -800.0);
					float shine_value2 = 0.5 + 0.5 * cos(t_y - floor(time*0.03)) * sin(t_x - floor(time*0.06));
					tColorOut.r = mix((r2-r1)*fade + r1, 1.0, isStar1 * shine_value1 + isStar2 * shine_value2);
                    tColorOut.g = mix((g2-g1)*fade + g1, 1.0, isStar1 * shine_value1 + isStar2 * shine_value2);
                    tColorOut.b = mix((b2-b1)*fade + b1, 1.0, isStar1 * shine_value1 + isStar2 * shine_value2);
				}
			} else if (special == 10){ //Dreamscape Fors (results screen version)
				if (i == 5){
					float fade = 1.0 - clamp((v_vPosition.y - (playerY+240.0))/280.0, 0.0, 1.0); //0 at bottom, 1 at top
					float denom = .00392; // 1.0 / 255.0
					float r1 = 150.0*denom;
					float g1 = 14.0*denom;
					float b1 = 166.0*denom;
					float r2 = 24.0*denom;
					float g2 = 4.0*denom;
					float b2 = 76.0*denom;
					float temp_time = 137.0; //random number
					float t_x = floor((playerX - v_vPosition.x) * 0.5);
		            float t_y = floor((playerY - v_vPosition.y) * 0.5);
		            float modx1 = mod(t_x,32.0);
		            float mody1 = mod(t_y,32.0);
					float isStar1 = float((modx1 == 0.0 && mody1 == 0.0) || (modx1 == 16.0 && mody1 == 16.0));
					float shine_value1 = 0.5 + 0.5 * sin(t_y + floor(temp_time*0.04)) * cos(t_x + floor(temp_time*0.02));
					float modx2 = mod(t_x,20.0);
		            float mody2 = mod(t_y,20.0);
					float isStar2 = float((modx2 == 4.0 && mody2 == 8.0) || (modx2 == 12.0 && mody2 == 0.0));
					float shine_value2 = 0.5 + 0.5 * cos(t_y - floor(temp_time*0.03)) * sin(t_x - floor(temp_time*0.06));
					tColorOut.r = mix((r2-r1)*fade + r1, 1.0, isStar1 * shine_value1 + isStar2 * shine_value2);
                    tColorOut.g = mix((g2-g1)*fade + g1, 1.0, isStar1 * shine_value1 + isStar2 * shine_value2);
                    tColorOut.b = mix((b2-b1)*fade + b1, 1.0, isStar1 * shine_value1 + isStar2 * shine_value2);
				}
			} else if (special == 8) { //summit kragg
                if (i == 0){
                    if (v_vPosition.y < effectY){
                        //replace with snow texture
                        tColorOut.r = 0.81960;//0.73725;//v_vTexcoord.x;
                        tColorOut.g = 0.83529;//0.76078;//v_vTexcoord.y;
                        tColorOut.b = 0.86667;//0.80784;
                    } else if (v_vPosition.y < effectY + 8.0){
                        float t_y = floor((playerY - v_vPosition.y) * 0.5) * 2.0;
                        float t_a = (t_y - effectY)*0.125;
                        float t_dither = (t_a * 4.0) + 1.0; //1 at top 4 at bottom
                        float t_x = floor((playerX - v_vPosition.x) * 0.5) + mod(t_dither, 2.0);
                        t_y = floor(v_vPosition.y * 0.5) * 2.0;
                        t_a = (t_y - effectY)*0.125;
                        if (mod(t_x, 2.0) < 1.0){
                            tColorOut.r = mix(0.81960,colorOut[i].r,t_a);
                            tColorOut.g = mix(0.83529,colorOut[i].g,t_a);
                            tColorOut.b = mix(0.86667,colorOut[i].b,t_a);
                        }
                    }
                }
            }
            
            //American Wrastor
            float t_x = floor((playerX - v_vPosition.x) * 0.5);
            float t_y = floor((playerY - v_vPosition.y) * 0.5);
            float modx = mod(t_x,4.0);
            float mody = mod(t_y,4.0);
            float isStar = float(special == 1 && i == 1 && ((modx == 0.0 && mody == 0.0) || (modx == 2.0 && mody == 2.0)));
            tColorOut.r = mix(tColorOut.r, 1.0, isStar * 0.5);
            tColorOut.g = mix(tColorOut.g, 1.0, isStar * 0.5);
            tColorOut.b = mix(tColorOut.b, 1.0, isStar * 0.5);
            
            
            //Excaliburn
			//bool isGolden = ((tColorOut.r == 228.0/255.0 && tColorOut.g == 228.0/255.0 && tColorOut.b == 240.0/255.0) || (tColorOut.r == 121.0/255.0 && tColorOut.g == 122.0/255.0 && tColorOut.b == 195.0/255.0));
            float isScanline = float(((special == 3 && (i == 2 || i == 3)) || (special == 6)) && t_y > t_x * -0.3 + mod(time*2.0,200.0) - 100.0 && t_y < t_x * -0.3 + mod(time*2.0,200.0) - 96.0);
			tColorOut.r = mix(tColorOut.r, 1.0, isScanline * 0.7);
            tColorOut.g = mix(tColorOut.g, 1.0, isScanline * 0.7);
            tColorOut.b = mix(tColorOut.b, 1.0, isScanline * 0.7);
            //Champion Kragg
            isScanline = float(special == 4 && i == 0 && ((mod(t_y,200.0) > mod(t_x + time*2.0,200.0) && mod(t_y,200.0) < mod(t_x + time*2.0 + 6.0,200.0))));
            tColorOut.r = mix(tColorOut.r, 1.0, isScanline * 0.7);
            tColorOut.g = mix(tColorOut.g, 1.0, isScanline * 0.7);
            tColorOut.b = mix(tColorOut.b, 1.0, isScanline * 0.7);
			
			//Pool Party Ranno
            mody = mod(t_y,6.0);
            bool inFlowerPos1 = (modx == 1.0 && (mody == 0.0 || mody == 2.0)) || (mody == 1.0 && (modx == 0.0 || modx == 2.0));
            bool inFlowerPos2 = (modx == 3.0 && (mody == 3.0 || mody == 5.0)) || (mody == 4.0 && (modx == 0.0 || modx == 2.0));
            bool inFlowerPos = (inFlowerPos1 || inFlowerPos2);
            float isFlower = float(special == 5 && i == 2 && inFlowerPos);
            tColorOut.r = mix(tColorOut.r, 1.0, isFlower * 0.8);
            tColorOut.g = mix(tColorOut.g, 1.0, isFlower * 0.8);
            tColorOut.b = mix(tColorOut.b, 1.0, isFlower * 0.8);
            
            
            vec4 colorOutHSV = vec4( rgb_to_hsv( tColorOut.rgb ), tColorOut.a);
            
            colorResult = mix( tColorOut,
                              vec4 ( hsv_to_rgb( vec3( mod( colorOutHSV.r + colorDelta.r, 1.0 ),
                                                     clamp( colorOutHSV.g + colorDelta.g, 0.0, 1.0 ),
                                                     clamp( colorOutHSV.b + colorDelta.b, 0.0, 1.0 ) ) ), 
                                     clamp( tColorOut.a + colorDelta.a, 0.0, 1.0) ),
                              blend[i].x );
        }
    }
    
    //Genesis Forsburn
    /*if (special == 2){
        for (float xOffset = -0.01; xOffset <= 0.01; xOffset += 0.005){
            for (float yOffset = -0.01; yOffset <= 0.01; yOffset += 0.005){
                vec4 colorPixel2 = texture2D( gm_BaseTexture, v_vTexcoord + vec2(xOffset, yOffset) );
                vec4 colorHSV2 = vec4( rgb_to_hsv( colorPixel2.rgb ), colorPixel2.a);
                
                vec4 colorInHSV2 = vec4( rgb_to_hsv( colorIn[2].rgb ), colorIn[2].a);
                vec4 colorInHSV3 = vec4( rgb_to_hsv( colorIn[3].rgb ), colorIn[3].a);
                vec4 colorInHSV4 = vec4( rgb_to_hsv( colorIn[4].rgb ), colorIn[4].a);
                vec4 colorDelta2 = colorHSV2 - colorInHSV2;
                vec4 colorDelta3 = colorHSV2 - colorInHSV3;
                vec4 colorDelta4 = colorHSV2 - colorInHSV4;
                if (abs(colorDelta2.r)>0.5) colorDelta2.r -= sign(colorDelta2.r);
                if (abs(colorDelta3.r)>0.5) colorDelta3.r -= sign(colorDelta3.r);
                if (abs(colorDelta4.r)>0.5) colorDelta4.r -= sign(colorDelta4.r);
                
                if ( all( lessThanEqual( abs(colorDelta2), colorTolerance[2] ) )
                ||   all( lessThanEqual( abs(colorDelta3), colorTolerance[3] ) )
                ||   all( lessThanEqual( abs(colorDelta4), colorTolerance[4] ) )) {
                    colorResult.r += 0.1;
                    if (colorResult.a == 0.0){
                        colorResult.g = 0.0;
                        colorResult.b = 0.0;
                    }
                    colorResult.a = clamp(colorResult.a + 0.1, 0.1, 1.0);
                }
            }
        }
    }*/
    
    gl_FragColor = v_vColour * colorResult;
}