/**
 * @license
 * Copyright 2019 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * =============================================================================
 */

interface Dimensions {
  x?: number;
  y?: number;
  width: number;
  height: number;
  depth: number;
}

export function vertexShaderSource() {
  return `#version 300 es
precision highp float;
precision highp int;

in vec2 position;
in vec2 texCoords;
out vec2 uv;

void main() {
  uv = texCoords;
  gl_Position = vec4(position, 0, 1);
}`;
}

export function fragmentShaderSource(
    sourceDims: Dimensions, targetDims: Dimensions, alignCorners: boolean) {
  const sWidth = sourceDims.width;
  const sHeight = sourceDims.height;
  const tWidth = targetDims.width;
  const tHeight = targetDims.height;

  const effectiveInSize: [number, number] = [
    (alignCorners && tWidth > 1) ? sWidth - 1 : sWidth,
    (alignCorners && tHeight > 1) ? sHeight - 1 : sHeight,
  ];

  const effectiveOutSize: [number, number] = [
    (alignCorners && tWidth > 1) ? tWidth - 1 : tWidth,
    (alignCorners && tHeight > 1) ? tHeight - 1 : tHeight,
  ];

  const roundBase = alignCorners ? '0.5' : '0.0';

  const outputFragType = targetDims.depth === 3 ? 'vec3' : 'vec4';
  const outputFragColor =
      targetDims.depth === 3 ? 'vec3(texSample)' : 'texSample';

  const source = `#version 300 es
precision highp float;

uniform sampler2D inputTexture;
in vec2 uv;
out ${outputFragType} fragColor;

vec2 sourceDims = vec2(${sWidth}, ${sHeight});
vec2 targetDims = vec2(${tWidth}, ${tHeight});

const vec2 inputToOutputRatio = vec2(
    ${effectiveInSize[0] / effectiveOutSize[0]},
    ${effectiveInSize[1] / effectiveOutSize[1]});

void main() {
  ivec2 targetCoords = ivec2(uv * targetDims);

  vec2 sourceCoords = vec2(targetCoords) * inputToOutputRatio;
  ivec2 iSourceCoords = ivec2(min(
    sourceDims - 1.0,
    floor(sourceCoords + ${roundBase})));

  vec4 texSample = texelFetch(inputTexture, iSourceCoords, 0);
  fragColor = ${outputFragColor};
}
`;

  return source;
}

export function vertices() {
  return new Float32Array([
    // clang-format off
    -1, -1,
    -1, 1,
    1, 1,
    1, 1,
    -1, -1,
    1, -1,
    // clang-format on
  ]);
}

export function texCoords() {
  return new Float32Array([
    // clang-format off
    0, 0,
    0, 1,
    1, 1,
    1, 1,
    0, 0,
    1, 0,
    // clang-format on
  ]);
}
