# encoding: utf-8
# from http://stackoverflow.com/a/9857493/445598
# because of
# `incompatible encoding regexp match (UTF-8 regexp with ASCII-8BIT string) (Encoding::CompatibilityError)`
require 'zip'

module Gym
  class XcodebuildFixes
    class << self
      # Determine whether it is a Swift project and, eventually, include all required libraries to copy from Xcode's toolchain directory.
      # Since there's no "xcodebuild" target to do just that, it is done post-build when exporting an archived build.
      def swift_library_fix
        require 'fileutils'

        return if check_for_swift PackageCommandGenerator

        Helper.log.info "Packaging up the Swift Framework as the current app is a Swift app" if $verbose
        ipa_swift_frameworks = Dir["#{PackageCommandGenerator.appfile_path}/Frameworks/libswift*"]

        Dir.mktmpdir do |tmpdir|
          # Copy all necessary Swift libraries to a temporary "SwiftSupport" directory so that we can
          # easily add it to the .ipa later.
          swift_support = File.join(tmpdir, "SwiftSupport")

          Dir.mkdir(swift_support)

          ipa_swift_frameworks.each do |path|
            framework = File.basename(path)

            FileUtils.copy_file("#{Xcode.xcode_path}/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/iphoneos/#{framework}", File.join(swift_support, framework))
          end

          # Add "SwiftSupport" to the .ipa archive
          Dir.chdir(tmpdir) do
            command_parts = ["zip --recurse-paths '#{PackageCommandGenerator.ipa_path}' SwiftSupport"]
            command_parts << "> /dev/null" unless $verbose
            Runner.new.print_command(command_parts, "Fix Swift embedded code if needed") if $verbose

            FastlaneCore::CommandExecutor.execute(command: command_parts,
                                                print_all: false,
                                            print_command: !Gym.config[:silent],
                                                    error: proc do |output|
                                                      ErrorHandler.handle_package_error(output)
                                                    end)
          end
        end
      end

      # @param the PackageCommandGenerator
      # @return true if swift
      def check_for_swift(pcg)
        Helper.log.info "Checking for Swift framework" if $verbose
        default_swift_libs = "#{pcg.appfile_path}/Frameworks/libswift.*" # note the extra ., this is a string representation of a regexp
        zip_entries_matching(pcg.ipa_path, /#{default_swift_libs}/).count > 0
      end

      # return the entries (files or directories) in the zip matching the pattern
      # @param zipfile a zipfile
      # @return the files or directories matching the pattern
      def zip_entries_matching(zipfile, file_pattern)
        files = []
        Zip::File.open(zipfile) do |zip_file|
          zip_file.each do |entry|
            files << entry.name if entry.name.force_encoding("utf-8").match file_pattern
          end
        end
        files
      end
    end
  end
end
