// 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 'dart:math' as math;
import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:pool/pool.dart';
import 'package:process/process.dart';

import '../../artifacts.dart';
import '../../base/error_handling_io.dart';
import '../../base/file_system.dart';
import '../../base/io.dart';
import '../../base/logger.dart';
import '../../build_info.dart';
import '../../convert.dart';
import '../../devfs.dart';
import '../build_system.dart';

/// The output shader format that should be used by the [ShaderCompiler].
enum ShaderTarget {
  impellerAndroid('--opengl-es'),
  impelleriOS('--metal-ios'),
  sksl('--sksl');

  const ShaderTarget(this.target);

  final String target;
}

/// A wrapper around [ShaderCompiler] to support hot reload of shader sources.
class DevelopmentShaderCompiler {
  DevelopmentShaderCompiler({
    required ShaderCompiler shaderCompiler,
    required FileSystem fileSystem,
    @visibleForTesting math.Random? random,
  }) : _shaderCompiler = shaderCompiler,
       _fileSystem = fileSystem,
       _random = random ?? math.Random();

  final ShaderCompiler _shaderCompiler;
  final FileSystem _fileSystem;
  final Pool _compilationPool = Pool(4);
  final math.Random _random;

  late ShaderTarget _shaderTarget;
  bool _debugConfigured = false;

  /// Configure the output format of the shader compiler for a particular
  /// flutter device.
  void configureCompiler(TargetPlatform? platform, { required bool enableImpeller }) {
    switch (platform) {
      case TargetPlatform.ios:
        _shaderTarget = enableImpeller ? ShaderTarget.impelleriOS : ShaderTarget.sksl;
        break;
      case TargetPlatform.android_arm64:
      case TargetPlatform.android_x64:
      case TargetPlatform.android_x86:
      case TargetPlatform.android_arm:
      case TargetPlatform.android:
        _shaderTarget = enableImpeller ? ShaderTarget.impellerAndroid : ShaderTarget.sksl;
        break;
      case TargetPlatform.darwin:
      case TargetPlatform.linux_x64:
      case TargetPlatform.linux_arm64:
      case TargetPlatform.windows_x64:
      case TargetPlatform.fuchsia_arm64:
      case TargetPlatform.fuchsia_x64:
      case TargetPlatform.tester:
      case TargetPlatform.web_javascript:
        assert(!enableImpeller);
        _shaderTarget = ShaderTarget.sksl;
        break;
      case null:
        return;
    }
    _debugConfigured = true;
  }

  /// Recompile the input shader and return a devfs content that should be synced
  /// to the attached device in its place.
  Future<DevFSContent?> recompileShader(DevFSContent inputShader) async {
    assert(_debugConfigured);
    final File output = _fileSystem.systemTempDirectory.childFile('${_random.nextDouble()}.temp');
    late File inputFile;
    bool cleanupInput = false;
    Uint8List result;
    PoolResource? resource;
    try {
      resource = await _compilationPool.request();
      if (inputShader is DevFSFileContent) {
        inputFile = inputShader.file as File;
      } else {
        inputFile = _fileSystem.systemTempDirectory.childFile('${_random.nextDouble()}.temp');
        inputFile.writeAsBytesSync(await inputShader.contentsAsBytes());
        cleanupInput = true;
      }
      final bool success = await _shaderCompiler.compileShader(
        input: inputFile,
        outputPath: output.path,
        target: _shaderTarget,
        fatal: false,
      );
      if (!success) {
        return null;
      }
      result = output.readAsBytesSync();
    } finally {
      resource?.release();
      ErrorHandlingFileSystem.deleteIfExists(output);
      if (cleanupInput) {
        ErrorHandlingFileSystem.deleteIfExists(inputFile);
      }
    }
    return DevFSByteContent(result);
  }
}

/// A class the wraps the functionality of the Impeller shader compiler
/// impellerc.
class ShaderCompiler {
  ShaderCompiler({
    required ProcessManager processManager,
    required Logger logger,
    required FileSystem fileSystem,
    required Artifacts artifacts,
  }) : _processManager = processManager,
       _logger = logger,
       _fs = fileSystem,
       _artifacts = artifacts;

  final ProcessManager _processManager;
  final Logger _logger;
  final FileSystem _fs;
  final Artifacts _artifacts;

  /// The [Source] inputs that targets using this should depend on.
  ///
  /// See [Target.inputs].
  static const List<Source> inputs = <Source>[
    Source.pattern('{FLUTTER_ROOT}/packages/flutter_tools/lib/src/build_system/targets/shader_compiler.dart'),
    Source.hostArtifact(HostArtifact.impellerc),
  ];

  /// Calls impellerc, which transforms the [input] glsl shader into a
  /// platform specific shader at [outputPath].
  ///
  /// All parameters are required.
  ///
  /// If the shader compiler subprocess fails, it will print the stdout and
  /// stderr to the log and throw a [ShaderCompilerException]. Otherwise, it
  /// will return true.
  Future<bool> compileShader({
    required File input,
    required String outputPath,
    required ShaderTarget target,
    bool fatal = true,
  }) async {
    final File impellerc = _fs.file(
      _artifacts.getHostArtifact(HostArtifact.impellerc),
    );
    if (!impellerc.existsSync()) {
      throw ShaderCompilerException._(
        'The impellerc utility is missing at "${impellerc.path}". '
        'Run "flutter doctor".',
      );
    }

    final List<String> cmd = <String>[
      impellerc.path,
      target.target,
      '--iplr',
      '--sl=$outputPath',
      '--spirv=$outputPath.spirv',
      '--input=${input.path}',
      '--input-type=frag',
      '--include=${input.parent.path}',
    ];
    final Process impellercProcess = await _processManager.start(cmd);
    final int code = await impellercProcess.exitCode;
    if (code != 0) {
      final String stdout = await utf8.decodeStream(impellercProcess.stdout);
      final String stderr = await utf8.decodeStream(impellercProcess.stderr);
      _logger.printTrace(stdout);
      _logger.printError(stderr);
      if (fatal) {
        throw ShaderCompilerException._(
          'Shader compilation of "${input.path}" to "$outputPath" '
          'failed with exit code $code.\n'
          'impellerc stdout:\n$stdout\n'
          'impellerc stderr:\n$stderr',
        );
      }
      return false;
    }
    ErrorHandlingFileSystem.deleteIfExists(_fs.file('$outputPath.spirv'));
    return true;
  }
}

class ShaderCompilerException implements Exception {
  ShaderCompilerException._(this.message);

  final String message;

  @override
  String toString() => 'ShaderCompilerException: $message\n\n';
}
