# frozen_string_literal: true
require 'safe_yaml'
SafeYAML::OPTIONS[:default_mode] = :safe

class Manifest
  attr_accessor :values

  def initialize(manifest_file)
    f = File.new manifest_file, 'r'
    @values = YAML.load f.read
  end

  def name
    "#{@values['registry']}/#{@values['name']}:#{@values['version']}"
  end
end

describe Manifest do
  def testing_for(s)
    puts "Testing for #{s}..."
  end

  def ok
    puts 'OK'
  end

  def symbolize(h)
    h.each_with_object({}) do |p, obj|
      obj[p.first.to_sym] = p.last
    end
  end

  def manifest_name_check(manifest)
    testing_for 'valid name'
    expect(manifest.values['name']).to_not eq(nil)
    expect(manifest.values['name'] =~ %r{\A[A-Za-z][A-Za-z0-9_-]+\z}).to_not eq(nil)
  end

  def manifest_version_check(manifest)
    testing_for 'existence of version'
    expect(manifest.values['version']).to_not eq(nil)
    expect(manifest.values['version'].is_a?(String)).to eq(true)
    expect(manifest.values['version']).to match(/\A[a-zA-Z0-9:._-]+\z/)
  end

  def manifest_registry_check(manifest)
    testing_for 'existence of registry'
    expect(manifest.values['registry']).to_not eq(nil)
    expect(manifest.values['registry'].is_a?(String)).to eq(true)
  end

  def manifest_test_types_check(manifest)
    testing_for 'test types'
    expect(manifest.values['test_types']).to_not eq(nil)
    expect(manifest.values['test_types'].empty?).to eq(false)
  end

  def manifest_configurable_check(manifest)
    testing_for 'configurability'
    if manifest.values['configurable']
      expect(manifest.values['default_config']).to_not be(nil)
    else
      expect(manifest.values['default_config']).to be(nil)
    end
  end
  CONFIG_SHIM = { ssh_user: '', ssh_key: '', target: '' }.freeze
  it 'validates the manifest file of all containers' do
    next if File.exist?("sectests/#{ENV['sectest_name']}/.parent_only")
    puts "Looking for valid manifest in: #{p}..."
    manifest = Manifest.new "sectests/#{ENV['sectest_name']}/manifest.yml"
    ok
    manifest_name_check(manifest)
    ok
    manifest_version_check manifest
    ok
    manifest_registry_check manifest
    ok
    testing_for 'valid prog args'
    expect(manifest.values['prog_args']).to_not eq(nil)
    expect(manifest.values['prog_args'].scan('%{target}').length).to eq(1)
    category = manifest.values['category']
    assert false unless category == 'blackbox' || category == 'whitebox'
    if category == 'blackbox'
      expect(manifest.values['prog_args'].scan('%{ssh_user}').length).to eq(0)
      expect(manifest.values['prog_args'].scan('%{ssh_key}').length).to eq(0)
    else
      expect(manifest.values['prog_args'].scan('%{ssh_user}').length).to eq(1)
      expect(manifest.values['prog_args'].scan('%{ssh_key}').length).to eq(1)
    end
    ok
    manifest_test_types_check manifest
    ok
    manifest_configurable_check manifest
    ok
    testing_for 'variants'
    puts 'No variants for this repo' unless Dir.exist?("sectests/#{ENV['sectest_name']}/variants")
    ok
    Dir.glob("sectests/#{ENV['sectest_name']}/variants/*").each do |variant|
      v_manifest = Manifest.new "#{variant}/manifest.yml"
      manifest_name_check v_manifest
      ok
      manifest_registry_check v_manifest
      ok
      manifest_version_check v_manifest
      ok
      manifest_test_types_check v_manifest
      ok
      manifest_configurable_check v_manifest
      ok
      if v_manifest.values['default_config'] && manifest.values['default_config']
        testing_for 'default config keys match base config keys'
        expect(v_manifest.values['default_config'].keys).to match_array(manifest.values['default_config'].keys)
        ok
      end
    end
    puts
  end
end