// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

library web_gl_test;

import 'dart:html';
import 'dart:web_gl';

import 'package:expect/minitest.dart';

final isAngleInstancedArrays = (v) => v is AngleInstancedArrays;
final isExtBlendMinMax = (v) => v is ExtBlendMinMax;
final isExtFragDepth = (v) => v is ExtFragDepth;
final isEXTsRgb = (v) => v is EXTsRgb;
final isExtShaderTextureLod = (v) => v is ExtShaderTextureLod;
final isExtTextureFilterAnisotropic = (v) => v is ExtTextureFilterAnisotropic;
final isOesElementIndexUint = (v) => v is OesElementIndexUint;
final isOesStandardDerivatives = (v) => v is OesStandardDerivatives;
final isOesTextureFloat = (v) => v is OesTextureFloat;
final isOesTextureFloatLinear = (v) => v is OesTextureFloatLinear;
final isOesTextureHalfFloat = (v) => v is OesTextureHalfFloat;
final isOesTextureHalfFloatLinear = (v) => v is OesTextureHalfFloatLinear;
final isOesVertexArrayObject = (v) => v is OesVertexArrayObject;
final isCompressedTextureAtc = (v) => v is CompressedTextureAtc;
final isCompressedTextureETC1 = (v) => v is CompressedTextureETC1;
final isCompressedTexturePvrtc = (v) => v is CompressedTexturePvrtc;
final isCompressedTextureS3TC = (v) => v is CompressedTextureS3TC;
final isDebugRendererInfo = (v) => v is DebugRendererInfo;
final isDebugShaders = (v) => v is DebugShaders;
final isDepthTexture = (v) => v is DepthTexture;
final isDrawBuffers = (v) => v is DrawBuffers;
final isLoseContext = (v) => v is LoseContext;

final isFunction = predicate((v) => v is Function);

// Test that various webgl extensions are available. Only test advertised
// supported extensions. If the extension has methods, we just test the presence
// of some methods - we don't test if functionality works.

main() {
  if (!RenderingContext.supported) return;

  const allExtensions = const [
    'ANGLE_instanced_arrays',
    'EXT_blend_minmax',
    'EXT_color_buffer_float',
    'EXT_color_buffer_half_float',
    'EXT_disjoint_timer_query',
    'EXT_frag_depth',
    'EXT_sRGB',
    'EXT_shader_texture_lod',
    'EXT_texture_filter_anisotropic',
    'OES_element_index_uint',
    'OES_standard_derivatives',
    'OES_texture_float',
    'OES_texture_float_linear',
    'OES_texture_half_float',
    'OES_texture_half_float_linear',
    'OES_vertex_array_object',
    'WEBGL_color_buffer_float',
    'WEBGL_compressed_texture_atc',
    'WEBGL_compressed_texture_es3',
    'WEBGL_compressed_texture_etc1',
    'WEBGL_compressed_texture_pvrtc',
    'WEBGL_compressed_texture_s3tc',
    'WEBGL_debug_renderer_info',
    'WEBGL_debug_shaders',
    'WEBGL_depth_texture',
    'WEBGL_draw_buffers',
    'WEBGL_lose_context',
  ];

  getExtension(String name) {
    expect(name, anyOf(allExtensions), reason: 'unknown extension');
    var canvas = new CanvasElement();
    var context = canvas.getContext3d();
    expect(context, isNotNull);
    var supportedExtensions = context.getSupportedExtensions();
    if (supportedExtensions.contains(name)) {
      var extension = context.getExtension(name);
      expect(extension, isNotNull);
      return extension;
    }
    return null;
  }

  testType(name, typeMatcher) {
    test('type', () {
      var extension = getExtension(name);
      if (extension == null) return;
      expect(extension, predicate(typeMatcher));
      // Ensure that isInstanceOf<X> is not instantiated for an erroneous type
      // X.  If X is erroneous, there is only a warning at compile time and X is
      // treated as dynamic, which would make the above line pass.
      expect(typeMatcher(1), false, reason: 'invalid typeMatcher');
    });
  }

  group('ANGLE_instanced_arrays', () {
    const name = 'ANGLE_instanced_arrays';
    testType(name, isAngleInstancedArrays);
    test('vertexAttribDivisorAngle', () {
      AngleInstancedArrays extension = getExtension(name);
      if (extension == null) return;
      expect(extension.vertexAttribDivisorAngle, isFunction);
    });
  });

  group('EXT_blend_minmax', () {
    testType('EXT_blend_minmax', isExtBlendMinMax);
  });

  group('EXT_frag_depth', () {
    testType('EXT_frag_depth', isExtFragDepth);
  });

  group('EXT_sRGB', () {
    testType('EXT_sRGB', isEXTsRgb);
  });

  group('EXT_shader_texture_lod', () {
    testType('EXT_shader_texture_lod', isExtShaderTextureLod);
  });

  group('EXT_texture_filter_anisotropic', () {
    testType('EXT_texture_filter_anisotropic', isExtTextureFilterAnisotropic);
  });

  group('OES_element_index_uint', () {
    testType('OES_element_index_uint', isOesElementIndexUint);
  });

  group('OES_standard_derivatives', () {
    testType('OES_standard_derivatives', isOesStandardDerivatives);
  });

  group('OES_texture_float', () {
    testType('OES_texture_float', isOesTextureFloat);
  });

  group('OES_texture_float_linear', () {
    testType('OES_texture_float_linear', isOesTextureFloatLinear);
  });

  group('OES_texture_half_float', () {
    testType('OES_texture_half_float', isOesTextureHalfFloat);
  });

  group('OES_texture_half_float_linear', () {
    testType('OES_texture_half_float_linear', isOesTextureHalfFloatLinear);
  });

  group('OES_vertex_array_object', () {
    testType('OES_vertex_array_object', isOesVertexArrayObject);
  });

  group('WEBGL_compressed_texture_atc', () {
    testType('WEBGL_compressed_texture_atc', isCompressedTextureAtc);
  });

  group('WEBGL_compressed_texture_etc1', () {
    testType('WEBGL_compressed_texture_etc1', isCompressedTextureETC1);
  });

  group('WEBGL_compressed_texture_pvrtc', () {
    testType('WEBGL_compressed_texture_pvrtc', isCompressedTexturePvrtc);
  });

  group('WEBGL_compressed_texture_s3tc', () {
    testType('WEBGL_compressed_texture_s3tc', isCompressedTextureS3TC);
  });

  group('WEBGL_debug_renderer_info', () {
    testType('WEBGL_debug_renderer_info', isDebugRendererInfo);
  });

  group('WEBGL_debug_shaders', () {
    testType('WEBGL_debug_shaders', isDebugShaders);
  });

  group('WEBGL_depth_texture', () {
    testType('WEBGL_depth_texture', isDepthTexture);
  });

  group('WEBGL_draw_buffers', () {
    const name = 'WEBGL_draw_buffers';
    testType(name, isDrawBuffers);
    test('drawBuffersWebgl', () {
      DrawBuffers extension = getExtension(name);
      if (extension == null) return;
      expect(extension.drawBuffersWebgl, isFunction);
    });
  });

  group('WEBGL_lose_context', () {
    const name = 'WEBGL_lose_context';
    testType(name, isLoseContext);
    test('loseContext', () {
      LoseContext extension = getExtension(name);
      if (extension == null) return;
      expect(extension.loseContext, isFunction);
    });
  });
}
