require 'rbconfig'

$: << File.expand_path(File.join(File.dirname(__FILE__), "../lib"))
require "mini_portile2"

recipes = []
recipe_hooks = {}

def windows?
  RbConfig::CONFIG['target_os'] =~ /mswin|mingw32/
end

def arm64_darwin?
  RUBY_PLATFORM =~ /arm64-darwin/
end

# libiconv is still shipping an old version of automake that doesn't support arm64-darwin
unless arm64_darwin?
  libiconv = MiniPortile.new "libiconv", "1.15"
  libiconv.files << "ftp://ftp.gnu.org/pub/gnu/#{libiconv.name}/#{libiconv.name}-#{libiconv.version}.tar.gz"
  libiconv.patch_files = Dir[File.join(__dir__, "libiconv-patches", "*.patch")].sort
  recipes.push libiconv
end


# libxml2 2.9.13 is still shipping an old version of automake that doesn't support arm64-darwin
unless arm64_darwin?
  # test the version of libxml2 with an xz extension
  libxml2 = MiniPortile.new "libxml2", "2.9.13"
  libxml2.files << "https://download.gnome.org/sources/libxml2/2.9/libxml2-2.9.13.tar.xz"
  libxml2.configure_options += [
    "--without-python",
    "--without-readline",
  ]
  recipes.push libxml2
end


# libxml2 2.9.13 is still shipping an old version of automake that doesn't support arm64-darwin
unless windows? || arm64_darwin?
  # i can't get this version to build on Github Actions windows-latest / windows-2019
  sqlite3 = MiniPortile.new "sqlite3", "3.35.4"
  sqlite3.files << "https://www.sqlite.org/2021/sqlite-autoconf-3350400.tar.gz"

  recipes.push sqlite3
end


unless windows? || arm64_darwin?
  # i can't get this version to build on Github Actions windows-latest / windows-2019
  # c-ares
  c_ares = MiniPortile.new "c-ares", "1.7.5"
  c_ares.files << {
    url: "file://#{File.dirname(__FILE__)}/c-ares-1.7.5.tar.gz",
    md5: "800875fc23cd8e1924d8af9172ed33e7"
  }

  recipes.push c_ares
end


# zlib
class ZlibRecipe < MiniPortile
  def windows?
    !(host =~ /mswin|mingw/).nil?
  end

  def configure
    return super unless windows?

    Dir.chdir work_path do
      mk = File.read 'win32/Makefile.gcc'
      File.open 'win32/Makefile.gcc', 'wb' do |f|
        f.puts "BINARY_PATH = #{path}/bin"
        f.puts "LIBRARY_PATH = #{path}/lib"
        f.puts "INCLUDE_PATH = #{path}/include"

        cross_build? and
          mk.sub!(/^PREFIX\s*=\s*$/, "PREFIX = #{host}-")

        f.puts mk
      end
    end
  end

  def configure_defaults
    ["--static"]
  end

  def configured?
    return super unless windows?

    !!(File.read(File.join(work_path, 'win32/Makefile.gcc')) =~ /^BINARY_PATH/)
  end

  def compile
    return super unless windows?

    execute "compile", "make -f win32/Makefile.gcc"
  end

  def install
    return if installed?
    return super unless windows?

    execute "install", %Q(#{make_cmd} -f win32/Makefile.gcc install)
  end

  def cross_build?
    host != original_host
  end
end

zlib = ZlibRecipe.new "zlib", "1.2.8"
zlib.files << {
  # url: "http://zlib.net/#{zlib.name}-#{zlib.version}.tar.gz",
  url: "file://#{File.dirname(__FILE__)}/#{zlib.name}-#{zlib.version}.tar.gz",
  md5: "44d667c142d7cda120332623eab69f40",
}

recipes.push zlib

#
#  libyaml, using pkgconf for configuration
#
yaml = MiniPortile.new("yaml", "0.2.5")
yaml.files = [{
                url: "https://github.com/yaml/libyaml/releases/download/0.2.5/yaml-0.2.5.tar.gz",
                sha256: "c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4",
              }]
yaml.configure_options << "CFLAGS=-fPIC"
recipes.unshift(yaml)
recipe_hooks["yaml"] = lambda do |recipe|
  recipe.mkmf_config(pkg: "yaml-0.1", static: "yaml")

  expected = File.join(recipe.path, "lib", "libyaml.a")
  $libs.include?(expected) or raise(<<~MSG)
    assertion failed: $libs not updated correctly:
    #{$libs}
    should have included '#{expected}'
  MSG

  unless have_func("yaml_get_version", "yaml.h")
    raise("could not find libyaml development environment")
  end
end

namespace :ports do
  directory "ports"

  task :before do
    FileUtils.rm_rf(File.expand_path("tmp"), verbose: true);
    recipes.each do |recipe|
      FileUtils.rm_rf(recipe.path, verbose: true)
    end
  end
  task :all => :before

  recipes.each do |recipe|
    desc "Install port #{recipe.name} #{recipe.version}"
    task recipe.name => ["ports"] do |t|
      recipe.cook
      if hook = recipe_hooks[recipe.name]
        hook.call(recipe)
      else
        recipe.activate
      end
    end

    task :all => recipe.name
  end

  desc "Install all ports and display installation location"
  task :all do
    recipes.each do |recipe|
      puts "Artifacts of '#{recipe.name}' in '#{recipe.path}'"
    end
    puts "---"
    puts "LIBRARY_PATH: #{ENV['LIBRARY_PATH'].inspect}"
    puts "LDFLAGS: #{ENV['LDFLAGS'].inspect}"
    puts "---"
    puts "$INCFLAGS: #{$INCFLAGS.inspect}"
    puts "$CFLAGS: #{$CFLAGS.inspect}"
    puts "$LIBPATH: #{$LIBPATH.inspect}"
    puts "$libs: #{$libs.inspect}"
  end
end


desc "Adjust all recipes host for cross-compilation"
task :cross do
  recipes.each do |recipe|
    recipe.host = "i686-w64-mingw32"
  end
end
