precision mediump float;

varying vec2 textureCoordinate;

uniform sampler2D inputImageTexture;

uniform vec2 iResolution;
uniform float iTime;

#define PI 3.14159265359

vec2 rotate(vec2 uv, vec2 centerP, float rotation, float ratio) {
    vec2 ori = vec2(uv.x - centerP.x, (uv.y - centerP.y) * ratio);
    return vec2(ori.x * cos(rotation) - ori.y * sin(rotation), (ori.x * sin(rotation) + ori.y * cos(rotation)) / ratio) + centerP;
}

vec2 scale(vec2 uv, vec2 centerP, vec2 scalePro, float ratio) {
    vec2 ori = vec2(uv.x - centerP.x, (uv.y - centerP.y) * ratio);
    return vec2(ori.x, ori.y/ratio)/scalePro + centerP;
}

vec2 transform(vec2 uv, float params[5], float ratio) {
    vec2 pos = uv;
    pos -= (vec2(params[2], -0.5) + vec2(-0.5, params[3]));
    pos = scale(pos, vec2(0.5), vec2(params[0], params[1]), ratio);
    pos = rotate(pos, vec2(0.5), -params[4]/180.0*PI, ratio);
    return pos;
}

int inside(vec2 uv, vec4 edge) {
    return (uv.x >= edge.x && uv.x <= (edge.x + edge.z) && uv.y >= edge.y && uv.y <= (edge.y + edge.w)) ? 1 : 0;
}

void main(void) {
    vec2 uv = textureCoordinate;

    float period = 1.0;
    float halfPer = period / 2.0;
    float time = mod(iTime, period);

    float rotation;
    if (time < halfPer/3.0) {
        rotation = mix(0.0, PI/120.0, 1.0 - pow(1.0 - time * 3.0/halfPer, 3.0));
    } else if (time < halfPer) {
        rotation = mix(PI/120.0, -PI/330.0, (time - halfPer/3.0) * 1.5 / halfPer);
    } else {
        rotation = mix(-PI/330.0, 0.0, (time - halfPer)/halfPer);
    }
    time = halfPer - abs(time - halfPer);
    float scalePro = mix(1.0, 1.08, time/halfPer);
    float xOffset = mix(0.0, 0.073, time/halfPer);
    float yOffset = mix(0.0, 0.015, time/halfPer);

    if (inside(uv, vec4(0.0, 0.0, 1.0, 1.0)) == 1) {
        vec2 st = vec2(uv.x - xOffset, uv.y - yOffset);
        st = scale(st, vec2(0.5), vec2(scalePro, scalePro), iResolution.y/iResolution.x);
        st = rotate(st, vec2(0.5), rotation, iResolution.y/iResolution.x);
        st = vec2(abs(mod(st.x + 1.0, 2.0) - 1.0), abs(mod(st.y + 1.0, 2.0) - 1.0));

        gl_FragColor = texture2D(inputImageTexture, st);
    }
}