// https://iquilezles.org/articles/distfunctions2d/
float sdRoundedBox( in vec2 p, in vec4 b, in float r )
{
    vec2 q = abs(p-b.xy)-b.zw+r;
    return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r;
}

float sdRoundedBox( in vec2 p, in vec2 bl, in vec2 tr, in float r )
{
    vec2 c = (bl+tr)*0.5;
    vec2 s = (tr-bl)*0.5;
    vec2 q = abs(p-c)-s+r;
    return min(max(q.x,q.y),0.0) + length(max(q,0.0)) - r;
}

// https://www.shadertoy.com/view/4djSRW
float hash12(vec2 p)
{
	vec3 p3  = fract(vec3(p.xyx) * .1031);
    p3 += dot(p3, p3.yzx + 33.33);
    return fract((p3.x + p3.y) * p3.z);
}

float hash13(vec3 p3)
{
	p3  = fract(p3 * .1031);
    p3 += dot(p3, p3.zyx + 31.32);
    return fract((p3.x + p3.y) * p3.z);
}

// https://www.shadertoy.com/view/ldKGRR
// Modified by timmaffett
float D(vec2 p, float n) {  // display digit
    int i=int(p.y), b=int(exp2(floor(30.-p.x-n*3.)));
    i = ( p.x<0.||p.x>3.? 0:
                         //  0   1   2   3   4   5   6   7   8   9
        i==5? 973012991: // 111 001 111 111 101 111 111 111 111 111
        i==4? 690407533: // 101 001 001 001 101 100 100 001 101 101
        i==3? 704642687: // 101 001 111 111 111 111 111 001 111 111
        i==2? 696556137: // 101 001 100 001 001 001 101 001 101 001
        i==1? 972881535: // 111 001 111 111 001 111 111 001 111 111
         0 )/b;
 	return float(i-i/2*2);

   /* old style 4 has row i==5 as ==972980223 */
}

float N(vec2 p, float v) {  // display number
    for (float n=1.; n>=0.; n--)  // print digit 1 to 0 ( negative = fractionals )
        if ((p.x-=4.)<3.) return D(p,floor(mod(v/pow(10.,n),10.)));
    return 0.;
}
// A digital clock (only shows minutes and seconds)
// Inspired by https://www.shadertoy.com/view/Mt3XW8
// Some functions are borrowed from iq, Dave_Hoskins, and FabriceNeyret2 (see Common tab)
// Thanks to timmaffett, I am able to render a full "4".

// Now features gpu sound (stolen from athibaul, see Sound tab)!
// Rewind if you cannot hear any sound.

#define GRID_COUNT_Y 11.0
#define ACTIVE_TIME 0.3

float getTimeDigits(vec2 blockIndex, float dateW)
{
    float n = 0.0f;

    if(abs(blockIndex.y-0.5f)==1.0f && blockIndex.x==0.5f) n=1.0f;

    blockIndex += vec2(12.0f, 3.0f);
    float minutes = mod(dateW, 3600.0f) / 60.0f;
    n += N(blockIndex, minutes);
    blockIndex -= vec2(10.0f, 0.0f);
    float seconds = mod(dateW, 60.0f);
    n += N(blockIndex, seconds);

    return n;
}

vec3 renderBlock(vec2 blockUV, vec3 colorTop, vec3 colorBottom, float invPixelCountY, float progress)
{
    vec4 box1Params = vec4(0.05f, 0.05f, 0.95f, 0.95f);
    float box1Radius = 0.05f;
    float sdfBox1 = sdRoundedBox(blockUV, box1Params.xy, box1Params.zw, box1Radius);
    float box1 = smoothstep(0.0f, 1.5f * invPixelCountY, sdfBox1);

    float sinVal = sin(progress * 1.5708);
    float cosVal = cos(progress * 1.5708);
    float seperatorThickness = 0.06f;
    float seperator = (1.0f - seperatorThickness * 0.5f) - sinVal * (1.0f - seperatorThickness);

    float minMargin = 0.01f;
    float maxMargin = 0.05f;
    float sideMargin = 0.04f;
    float bottomMargin = minMargin;
    float topMargin = minMargin;

    // bottom
    vec4 box2Params = vec4(0.05f + minMargin, 0.05f + bottomMargin,
                            0.95f - sideMargin, seperator-seperatorThickness*0.5f);
    float box2Radius = 0.05f;
    float sdfBox2 = sdRoundedBox(blockUV, box2Params.xy, box2Params.zw, box2Radius);
    float box2 = smoothstep(0.0f, 1.5f * invPixelCountY, sdfBox2);

    // top
    vec4 box3Params = vec4(0.05f + minMargin, seperator+seperatorThickness*0.5f,
                            0.95f - sideMargin, 0.95f-topMargin);
    float box3Radius = 0.05f;
    float sdfBox3 = sdRoundedBox(blockUV, box3Params.xy, box3Params.zw, box3Radius);
    float box3 = smoothstep(0.0f, 1.5f * invPixelCountY, sdfBox3);

    vec2 lightSource = normalize(vec2(0.5, 2.0f));
    // background
    vec3 color0 = vec3(0.40f, 0.40f, 0.20f);
    // edge
    vec3 color1 = vec3(0.95f, 0.95f, 0.85f) * lightSource.y;
    // bottom
    vec3 color2 = colorBottom * (dot(lightSource, vec2(cosVal, -sinVal)) * 0.3f + 0.7f);
    // top
    vec3 color3 = colorTop * (dot(lightSource, vec2(sinVal, cosVal)) * 0.3f + 0.7f);

    vec3 color = mix(color1, color0, box1);
    color = mix(color2, color, box2);
    color = mix(color3, color, box3);
    return color;
}

void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
    vec2 pixelCount = iResolution.yy / GRID_COUNT_Y;
    vec2 centerFragCoord = fragCoord+0.5f*pixelCount-(iResolution.xy)*0.5f;

    float invPixelCountY = 1.0f / pixelCount.y;
    ivec2 blockIndex = ivec2(floor(centerFragCoord * invPixelCountY));
    vec2 blockUV = mod(centerFragCoord, pixelCount) * invPixelCountY;

    float floorTime = floor(iTime);
    float fractTime = fract(iTime);
    float inactive = 1.0f - ACTIVE_TIME;
    float randomVal = hash13(vec3(vec2(blockIndex), floorTime)) * inactive;

    // In order to sync with sound tab, we need to tweek iDate.w a little bit
    float initDateW = floor(iDate.w - iTime);
    float dateW = initDateW + floorTime;
    // For thumbnail (I gave up)
    if(iFrame <= 5 && iResolution.x < 200.0) dateW += inactive;

    float progress = clamp((fractTime-randomVal) / ACTIVE_TIME, 0.0f, 1.0f);
    // if(iMouse.z > 0.0f) {progress = 1.0f - fract(2.0f * iMouse.y / iResolution.y);}

    float d1 = getTimeDigits(vec2(blockIndex)+vec2(0.5f), dateW);
    float d2 = getTimeDigits(vec2(blockIndex)+vec2(0.5f), dateW+1.0f);

    vec3 colorBackground = vec3(0.95f, 0.95f, 0.85f);
    vec3 colorDigit = vec3(0.2f, 0.2f, 0.4f);
    vec3 color1 = mix(colorBackground, colorDigit, d1);
    vec3 color2 = mix(colorBackground, colorDigit, d2);
    vec3 color = renderBlock(blockUV, color2, color1, invPixelCountY, progress);

    fragColor = vec4(color, 1.0f);
}
