// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_system/targets/shader_compiler.dart';
import 'package:flutter_tools/src/globals.dart' as globals;

import '../src/common.dart';
import '../src/context.dart';

void main() {
  late BufferLogger logger;

  setUp(() {
    logger = BufferLogger.test();
  });

  Future<void> testCompileShader(String source) async {
    final Directory tmpDir = globals.fs.systemTempDirectory.createTempSync(
      'shader_compiler_test.',
    );
    final File file = tmpDir.childFile('test_shader.frag')
      ..writeAsStringSync(source);
    final ShaderCompiler shaderCompiler = ShaderCompiler(
      processManager: globals.processManager,
      logger: logger,
      fileSystem: globals.fs,
      artifacts: globals.artifacts!,
    );
    await shaderCompiler.compileShader(
      input: file,
      outputPath: tmpDir.childFile('test_shader.frag.out').path,
      target: ShaderTarget.sksl,
      json: false,
    );
  }

  testUsingContext('impellerc .iplr output has correct permissions', () async {
    if (globals.platform.isWindows) {
      return;
    }

    final String flutterRoot = getFlutterRoot();
    final String inkSparklePath = globals.fs.path.join(flutterRoot,
      'packages', 'flutter', 'lib', 'src', 'material', 'shaders',
      'ink_sparkle.frag');
    final Directory tmpDir = globals.fs.systemTempDirectory.createTempSync(
      'shader_compiler_test.',
    );
    final String inkSparkleOutputPath = globals.fs.path.join(
      tmpDir.path, 'ink_sparkle.frag',
    );

    final ShaderCompiler shaderCompiler = ShaderCompiler(
      processManager: globals.processManager,
      logger: logger,
      fileSystem: globals.fs,
      artifacts: globals.artifacts!,
    );
    final bool compileResult = await shaderCompiler.compileShader(
      input: globals.fs.file(inkSparklePath),
      outputPath: inkSparkleOutputPath,
      target: ShaderTarget.sksl,
      json: false,
    );
    final File resultFile = globals.fs.file(inkSparkleOutputPath);


    expect(compileResult, true);
    expect(resultFile.existsSync(), true);

    final int expectedMode = int.parse('644', radix: 8);
    expect(resultFile.statSync().mode & expectedMode, equals(expectedMode));
  });

  testUsingContext('Compilation error with in storage', () async {
    const String kShaderWithInput = '''
in float foo;

out vec4 fragColor;

void main() {
  fragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
''';

    expect(() => testCompileShader(kShaderWithInput), throwsA(isA<ShaderCompilerException>()
      .having(
        (ShaderCompilerException exception) => exception.message,
        'message',
        contains('SkSL does not support inputs'),
      ),
    ));
  });

  testUsingContext('Compilation error with UBO', () async {
    const String kShaderWithInput = '''
uniform Data {
  vec4 foo;
} data;

out vec4 fragColor;

void main() {
  fragColor = data.foo;
}
''';

    expect(() => testCompileShader(kShaderWithInput), throwsA(isA<ShaderCompilerException>()
      .having(
        (ShaderCompilerException exception) => exception.message,
        'message',
        contains('SkSL does not support UBOs or SSBOs'),
      ),
    ));
  });

  testUsingContext('Compilation error with texture arguments besides position or sampler', () async {
    const String kShaderWithInput = '''
uniform sampler2D tex;

out vec4 fragColor;

void main() {
  fragColor = texture(tex, vec2(0.5, 0.3), 0.5);
}
''';

    expect(() => testCompileShader(kShaderWithInput), throwsA(isA<ShaderCompilerException>()
      .having(
        (ShaderCompilerException exception) => exception.message,
        'message',
        contains('Only sampler and position arguments are supported in texture() calls'),
      ),
    ));
  });

  testUsingContext('Compilation error with uint8 uniforms', () async {
    const String kShaderWithInput = '''
#version 310 es

layout(location = 0) uniform uint foo;
layout(location = 0) out vec4 fragColor;

void main() {}
''';

    expect(() => testCompileShader(kShaderWithInput), throwsA(isA<ShaderCompilerException>()
      .having(
        (ShaderCompilerException exception) => exception.message,
        'message',
        contains('SkSL does not support unsigned integers'),
      ),
    ));
  });
}
