require 'erb'
require 'active_support'
require 'active_support/core_ext'
require 'ansi/bbcode'

module Debci
  module HTMLHelpers
    include ERB::Util
    include ActiveSupport::NumberHelper

    ICONS = {
      pass: 'thumbs-up',
      neutral: 'minus-circle',
      fail: 'thumbs-down',
      fail_passed_never: ['thumbs-down', 'ban'],
      fail_passed_current: ['thumbs-down', 'bolt'],
      fail_passed_old: ['thumbs-down', 'arrow-down'],
      tmpfail_pass: 'thumbs-up',
      tmpfail_fail: 'thumbs-down',
      tmpfail: 'question-circle',
      no_test_data: 'question',
    }.freeze

    def icon(status)
      status ||= :no_test_data
      Array(ICONS[status.to_sym]).map do |i|
        "<i class='#{status} fa fa-#{i}'></i>"
      end.join(' ')
    end

    def file_link(size, link_pattern)
      return unless size
      link_pattern % number_to_human_size(size)
    end

    def title_test_trigger_pin(test)
      title = ''
      unless test.trigger.blank?
        title << "Trigger:\n"
        title << h(test.trigger)
      end
      if test.pinned?
        title << "\n\n" unless test.trigger.blank?
        title << "Pinned packages:\n"
        expand_pin_packages(test).each do |pin|
          title << pin << "\n"
        end
      end
      title
    end

    def expand_pin_packages(test)
      return [] unless test.pinned?

      test.pin_packages.map do |pin|
        *packages, suite = pin
        Array(packages).map do |pkglist|
          String(pkglist).split(/\s*,\s*/).map do |pkg|
            "#{pkg} from #{suite}"
          end
        end
      end.flatten
    end

    def base_url
      "#{request.scheme}://#{request.host}#{['', request.port].compact.join(':')}"
    end

    def pkg_history_url(package, suite, arch)
      "/packages/#{package.prefix}/#{package.name}/#{suite}/#{arch}/"
    end

    def history_url(job)
      pkg_history_url(job.package, job.suite, job.arch)
    end

    def package_url(package)
      "/packages/#{package.prefix}/#{package.name}/"
    end

    def log_url(job)
      "#{history_url(job)}#{job.run_id}/"
    end

    def download_url(job)
      dir = [job.suite, job.arch, job.package.prefix, job.package.name].join('/')
      "/data/autopkgtest/#{dir}/#{job.run_id}/log.gz"
    end

    def log_links(job)
      if !job.status
        "<span class='fa fa-clock-o'></span>"
      elsif job.files_purged?
        "<span class='fa fa-trash' title='file has been removed due to data retention policy'></span>"
      else
        file_link(
          job.log_size,
          "<a href=\"#{log_url(job)}\">test log</a> &nbsp; <a href=\"#{download_url(job)}\"><span class=\"fa fa-download\"></span></a> <small>(%s)</small>"
        )
      end
    end

    # expand { SUITE } macro in URLs
    def expand_url(url, suite)
      url&.gsub('{SUITE}', suite)
    end

    # Converts ANSI codes to HTML. Escapes any HTML before even looking for
    # ANSI codes.
    def ansi_to_html(str)
      return str unless str
      input = str.gsub('<', '&lt;').gsub('>', '&gt;')
      return input unless input =~ /\e\[/
      begin
        result = ANSI::BBCode.ansi_to_html(input)
        result = result[0..-8] if result =~ %r{<br />\n$}
        result
      rescue StandardError
        # in case anything goes wrong with the conversion, just remove all ANSI
        # escape codes
        input.gsub(/\e\[[0-9;]+m/, "")
      end
    end

    # Returns a content-based URL to a static file
    def static_url(path)
      Debci::HTMLHelpers.static_url(path)
    end

    def stylesheet_tag(path)
      url = static_url(path)
      "<link rel=\"stylesheet\" type=\"text/css\" href=\"#{url}\"/>"
    end

    def javascript_tag(path)
      url = static_url(path)
      "<script type=\"text/javascript\" src=\"#{url}\"></script>"
    end

    def notice
      Debci::HTMLHelpers.notice
    end

    class << self
      def static_url(path)
        @static_url_cache ||= {}
        if @static_url_cache.key?(path)
          return @static_url_cache[path]
        end

        file = File.join(Debci.config.base_dir, 'public', path)
        tag = Digest::MD5.file(file).hexdigest
        @static_url_cache[path] = "#{path}?#{tag}"
      end

      def notice
        @notice ||=
          begin
            notice_file = File.join(Debci.config.config_dir, "notice.html")
            File.exist?(notice_file) ? File.read(notice_file) : ""
          end
      end
    end
  end
end