default_platform(:ios)

ENV["FASTLANE_XCODEBUILD_SETTINGS_RETRIES"] = "0"
ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "30"

SCREENSHOT_LANGUAGES = ["en-US", "zh-Hans"].freeze
SCREENSHOT_LOCALES = {
  "zh-Hans" => "zh_CN"
}.freeze

def reset_dir(path)
  FileUtils.rm_rf(path)
  FileUtils.mkdir_p(path)
end

def screenshot_locale(language)
  SCREENSHOT_LOCALES[language]
end

def write_screenshot_language_files(dir, language, locale)
  FileUtils.mkdir_p(dir)
  File.write(File.join(dir, "language.txt"), language)
  if locale
    File.write(File.join(dir, "locale.txt"), locale)
  else
    FileUtils.rm_f(File.join(dir, "locale.txt"))
  end
end

def shutdown_simulator(name)
  sh("xcrun simctl shutdown \"#{name}\" || true")
end

platform :ios do
  desc "Generate iOS screenshots"
  lane :screenshots do
    ENV["SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT"] = "10"
    screenshots_cache = File.expand_path("~/Library/Caches/tools.fastlane/screenshots")
    reset_dir(screenshots_cache)
    capture_screenshots
    shutdown_simulator("iPhone 11 Pro Max")
    shutdown_simulator("iPad Pro 13-inch (M4)")
  end
end

platform :mac do
  desc "Generate macOS screenshots"
  lane :screenshots do
    output_base_dir = File.expand_path("../screenshots/macos", __dir__)
    screenshots_cache_candidates = [
      File.expand_path("~/Library/Caches/tools.fastlane/screenshots"),
      File.expand_path("~/Library/Containers/io.nekohasekai.sfavt.SFMUITests.xctrunner/Data/Library/Caches/tools.fastlane/screenshots")
    ].uniq
    ENV["DISABLE_SWIFTLINT"] = "1"
    ENV["SCREENSHOT_WINDOW_PIXEL_HEIGHT"] = "1000"

    reset_dir(output_base_dir)

    SCREENSHOT_LANGUAGES.each do |language|
      output_dir = File.join(output_base_dir, language)
      ENV["SCREENSHOT_LANGUAGE"] = language
      locale = screenshot_locale(language)
      if locale
        ENV["SCREENSHOT_LOCALE"] = locale
      else
        ENV.delete("SCREENSHOT_LOCALE")
      end
      reset_dir(output_dir)
      screenshots_cache_candidates.each do |dir|
        reset_dir(dir)
        write_screenshot_language_files(dir, language, locale)
      end

      run_tests(
        project: "sing-box.xcodeproj",
        scheme: "SFM",
        destination: "platform=macOS",
        result_bundle: false,
        reinstall_app: false,
        app_identifier: "io.nekohasekai.sfavt",
        only_testing: ["SFMUITests/SnapshotTests"],
        number_of_retries: 0
      )

      copied = {}
      screenshots_cache_candidates.each do |dir|
        Dir.glob("#{dir}/Mac-*.png").each do |file|
          basename = File.basename(file)
          next if copied[basename]
          FileUtils.cp(file, output_dir)
          copied[basename] = true
        end
      end

      padded_files = Dir.glob("#{output_dir}/*.png")
      magick_bin = `which magick 2>/dev/null`.strip
      magick_bin = `which convert 2>/dev/null`.strip if magick_bin.empty?
      if magick_bin.empty?
        UI.user_error!("ImageMagick not found. Install it (magick/convert) to add shadow.")
      end

      canvas_width = 2880
      canvas_height = 1800
      target_width = 2620
      target_height = 1620
      shadow_opacity = 26

      padded_files.each do |file|
        size_output = sh(
          magick_bin,
          file,
          "-format",
          "%w %h",
          "info:",
          log: false
        ).strip
        opaque_output = sh(
          magick_bin,
          file,
          "-format",
          "%[opaque]",
          "info:",
          log: false
        ).strip
        width, height = size_output.split.map(&:to_i)
        has_transparency = opaque_output != "True"
        tmp_file = "#{file}.tmp.png"

        if has_transparency
          shadow_sigma = 24
          shadow_offset = 8
          shadow = "#{shadow_opacity}x#{shadow_sigma}+0+#{shadow_offset}"
          sh(
            magick_bin,
            file,
            "-alpha", "set",
            "-background", "none",
            "-trim",
            "+repage",
            "-resize",
            "#{target_width}x#{target_height}",
            "(",
            "+clone",
            "-background",
            "black",
            "-shadow",
            shadow,
            ")",
            "+swap",
            "-background",
            "white",
            "-layers",
            "merge",
            "+repage",
            "-gravity",
            "center",
            "-extent",
            "#{canvas_width}x#{canvas_height}",
            tmp_file
          )
        else
          scale = [
            target_width.to_f / width,
            target_height.to_f / height
          ].min
          scaled_width = (width * scale).round
          scaled_height = (height * scale).round
          mask_width = [scaled_width - 1, 1].max
          mask_height = [scaled_height - 1, 1].max
          corner_radius = [(28 * scale).round, 28].max
          shadow_sigma = [(16 * scale).round, 1].max
          shadow_offset = [(5 * scale).round, 1].max
          shadow = "#{shadow_opacity}x#{shadow_sigma}+0+#{shadow_offset}"
          sh(
            magick_bin,
            file,
            "-resize",
            "#{scaled_width}x#{scaled_height}",
            "-alpha",
            "set",
            "(",
            "-size",
            "#{scaled_width}x#{scaled_height}",
            "xc:none",
            "-fill",
            "white",
            "-draw",
            "roundrectangle 0,0 #{mask_width},#{mask_height},#{corner_radius},#{corner_radius}",
            ")",
            "-compose",
            "DstIn",
            "-composite",
            "-compose",
            "over",
            "(",
            "+clone",
            "-background",
            "black",
            "-shadow",
            shadow,
            ")",
            "+swap",
            "-background",
            "white",
            "-layers",
            "merge",
            "+repage",
            "-gravity",
            "center",
            "-extent",
            "#{canvas_width}x#{canvas_height}",
            tmp_file
          )
        end
        FileUtils.mv(tmp_file, file, force: true)
      end
    end
  end
end

platform :tvos do
  desc "Generate tvOS screenshots"
  lane :screenshots do
    output_base_dir = File.expand_path("../screenshots/tvos", __dir__)
    screenshots_cache = File.expand_path("~/Library/Caches/tools.fastlane/screenshots")

    reset_dir(output_base_dir)

    SCREENSHOT_LANGUAGES.each do |language|
      output_dir = File.join(output_base_dir, language)
      ENV["SCREENSHOT_LANGUAGE"] = language
      locale = screenshot_locale(language)
      if locale
        ENV["SCREENSHOT_LOCALE"] = locale
      else
        ENV.delete("SCREENSHOT_LOCALE")
      end
      reset_dir(output_dir)
      reset_dir(screenshots_cache)
      write_screenshot_language_files(screenshots_cache, language, locale)

      run_tests(
        project: "sing-box.xcodeproj",
        scheme: "SFT",
        devices: ["Apple TV 4K (3rd generation)"],
        result_bundle: false,
        reinstall_app: true,
        app_identifier: "io.nekohasekai.sfavt",
        only_testing: ["SFTUITests/SnapshotTests"],
        number_of_retries: 0,
        cloned_source_packages_path: "/tmp/fastlane_source_packages",
        derived_data_path: "/tmp/fastlane_derived_data"
      )

      Dir.glob("#{screenshots_cache}/*.png").each do |file|
        FileUtils.cp(file, output_dir)
      end
    end
    shutdown_simulator("Apple TV 4K (3rd generation)")
  end
end
