require 'artifactory'

module CiCd
  module Builder
    # noinspection RubySuperCallWithoutSuperclassInspection
    module Manifest
      module Repo
        class Artifactory < CiCd::Builder::Repo::Artifactory
          # include ::Artifactory::Resource

          # ---------------------------------------------------------------------------------------------------------------
          def initialize(builder)
            super
          end

          # ---------------------------------------------------------------------------------------------------------------
          def uploadToRepo(artifacts)
            @manifest = {}
            super
            if @vars[:return_code] == 0
              # Preserve the manifest (maybeUploadArtifactoryObject will add everything we upload to the instance var)
              manifest = @manifest.dup
              # Create a manifest for each product and store it.
              createProductManifests(manifest)
              # Get a super manifest of all products and store as learning-manifest
              createSuperManifest(manifest) # -#{@vars[:variant]}
              @manifest = manifest
            end
            # If we are asked to produce a PROJECTS_FILE then we do that from the manifest and components.
            unless ENV['PROJECTS_FILE'].nil?
              if @vars[:return_code] == 0
                if File.directory?(File.realdirpath(File.dirname(ENV['PROJECTS_FILE'])))
                  createProjectsFile
                else
                  @logger.error "The path to the PROJECTS_FILE (#{File.dirname(ENV['PROJECTS_FILE'])}) does not exist!"
                  @vars[:return_code] = Errors::NO_PROJECTS_PATH
                end
              end
            end
            @vars[:return_code]
          end

          # ---------------------------------------------------------------------------------------------------------------
          def createProjectsFile
            @logger.info __method__.to_s
            projects = {}
            project_names = {}
            unless ENV['PROJECT_NAMES'].nil?
              if File.exists?(ENV['PROJECT_NAMES'])
                @logger.info "Load PROJECT_NAMES: #{ENV['PROJECT_NAMES']}"
                project_names = JSON.load(IO.read(ENV['PROJECT_NAMES']))
              else
                @logger.error "The PROJECT_NAMES file (#{ENV['PROJECT_NAMES']}) does not exist!"
                @vars[:return_code] = Errors::NO_PROJECT_NAMES
              end
            end
            exts = Hash[@vars[:artifacts].map { |a| [a[:data][:name], File.extname(File.basename(a[:data][:file])).gsub(%r'^\.', '')] }]
            @manifest.each do |mod, man|
              man.each do |prod, build|
                projects[prod] = {
                    name: project_names[prod] || prod,
                    module: mod,
                    ext: exts[prod],
                    class_filter: '',
                }
              end
            end
            @logger.info "Save PROJECTS_FILE: #{ENV['PROJECTS_FILE']}"
            IO.write(ENV['PROJECTS_FILE'], JSON.pretty_generate(projects, {indent: "\t", space: ' '}))
          end

          def createSuperManifest(manifest)
            manifest_data = ''
            manifest.each do |mod, man|
              man.each do |k, v|
                manifest_data += "#{k}=#{v}\n"
              end
            end
            amn = artifactory_manifest_name # Just using a local iso invoking method_missing repeatedly ... ;)
            data = {module: amn, data: manifest_data, version: @vars[:build_ver], build: @vars[:build_num], properties: @properties_matrix}
            tempArtifactFile(amn, data)
            data[:sha1] = Digest::SHA1.file(data[:file]).hexdigest
            data[:md5] = Digest::MD5.file(data[:file]).hexdigest
            data[:name] = amn
            maybeUploadArtifactoryObject(data: data, artifact_module: amn, artifact_version: data[:version] || @vars[:version], file_name: '', file_ext: 'properties')
          end

          # ---------------------------------------------------------------------------------------------------------------
          def createProductManifests(manifest)
            manifest.each do |mod, man|
              manifest_data = ''
              man.each do |k, v|
                manifest_data += "#{k}=#{v}\n"
              end
              data = {module: mod, data: manifest_data, version: @vars[:build_ver], build: @vars[:build_num], properties: @properties_matrix}
              tempArtifactFile("#{mod}-manifest", data)
              data[:sha1] = Digest::SHA1.file(data[:file]).hexdigest
              data[:md5] = Digest::MD5.file(data[:file]).hexdigest
              data[:name] = "#{mod}-manifest"
              maybeUploadArtifactoryObject(data: data, artifact_module: data[:name], artifact_version: data[:version] || @vars[:version], file_name: '', file_ext: 'properties') # -#{@vars[:variant]}
            end
          end

          # ---------------------------------------------------------------------------------------------------------------
          def maybeUploadArtifactoryObject(args)
            super
            if @vars[:return_code] == 0
              data             = args[:data]
              artifact_module  = args[:artifact_module]
              artifact_version = args[:artifact_version]
              # file_ext         = args[:file_ext]
              # file_name        = args[:file_name]
              if @manifest[artifact_module].nil?
                @manifest[artifact_module] = {}
                file_name = artifact_module
              else
                file_name, _ = get_artifact_file_name_ext(data)
                if file_name.empty?
                  file_name = artifact_module
                else
                  file_name = "#{artifact_module}#{file_name}"
                end
              end
              @manifest[artifact_module][file_name] = artifact_version
            end

            @vars[:return_code]
          end

          private :createProductManifests, :createProjectsFile, :createSuperManifest
        end
      end
    end
  end
end

=begin

                {
                    "test-project": {
                        "name": "test-project",
                        "module": "test-server",
                        "ext": "war",
                        "class_filter": "role.role-1"
                    },
                    "test-project-2": {
                        "name": "test-project-2",
                        "module": "test-server2",
                        "ext": "zip",
                        "class_filter": "role.role-2"
                    },
                    "test-manifest": {
                        "name": "test-manifest",
                        "module": "test-manifest",
                        "ext": "properties",
                        "class_filter": ""
                    },
                    "test-manifest2": {
                        "name": "test-manifest2",
                        "module": "test-manifest2",
                        "ext": "properties",
                        "class_filter": ""
                    }
                }

=end