#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

$lib = File.expand_path('../lib', File.dirname(__FILE__))
$LOAD_PATH.unshift($lib)

require "Models/AppleConfig"
require "Models/AndroidConfig"
require "Models/Processor"
require "Models/Version"
require "Helper"
require "ZLogger"
require "AppleFetcher"
require "AndroidFetcher"
require "optparse"
require "yaml"
require "fileutils"

class Main
    def initialize

        ARGV << '-h' if ARGV.empty?

        OptionParser.new do |opts|
            opts.banner = "Usage: ZReviewTender [options]"

            basePath = ENV['PWD'] || ::Dir.pwd
            defaultConfigDirName = "config"
            defaultAppleConfigFileName = "apple.yml"
            defaultAndroidConfigFileName = "android.yml"
        
            opts.on('-a', '--apple[=CONFIGYMLFILEPATH]', 'execute apple platform, default config yml file path: /config/apple.yml, use --apple=CONFIG_YML_FILE_PATH specify config yml file path') do |configYMLFilePath|
                if configYMLFilePath.nil?
                    configYMLFilePath = "#{basePath}/#{defaultConfigDirName}/#{defaultAppleConfigFileName}"
                end
                configFileCheck(configYMLFilePath, "--apple=CONFIG_YML_FILE_PATH")

                puts "[ZReviewTender] run -a/-apple config yml file path: #{configYMLFilePath}"

                fetcher = parseConfigYMLFile(configYMLFilePath)
                fetcher.execute()

                checkLatestVersionOfZReviewTender()
            end 

            opts.on('-g', '--googleAndroid[=CONFIGYMLFILEPATH]', 'execute android platform, default config yml file path: /config/android.yml, use --googleAndroid=CONFIG_YML_FILE_PATH specify config yml file path') do |configYMLFilePath|
                if configYMLFilePath.nil?
                    configYMLFilePath = "#{basePath}/#{defaultConfigDirName}/#{defaultAndroidConfigFileName}"
                end
                configFileCheck(configYMLFilePath, "--googleAndroid=CONFIG_YML_FILE_PATH")

                puts "[ZReviewTender] run -g/-googleAndroid config yml file path: #{configYMLFilePath}"

                fetcher = parseConfigYMLFile(configYMLFilePath)
                fetcher.execute()

                checkLatestVersionOfZReviewTender()
            end 
            
            opts.on('-r', '--run=[=CONFIGFOLDERNAME]', 'execute both android and apple, specify a /config folder path') do |configFolderName|
                if configFolderName.nil?
                    configFolderName = defaultConfigDirName
                end

                puts "[ZReviewTender] run -r/--run config folder path: #{configFolderName}"

                androidConfigFilePath = "#{basePath}/#{configFolderName}/#{defaultAndroidConfigFileName}"
                configFileCheck(androidConfigFilePath, "--googleAndroid=CONFIG_YML_FILE_PATH")
                
                fetcher = parseConfigYMLFile(androidConfigFilePath)
                fetcher.execute()
                
                #
                
                appleConfigFilePath = "#{basePath}/#{configFolderName}/#{defaultAppleConfigFileName}"
                configFileCheck(appleConfigFilePath, "--apple=CONFIG_YML_FILE_PATH")

                fetcher = parseConfigYMLFile(appleConfigFilePath)
                fetcher.execute()

                checkLatestVersionOfZReviewTender()
            end

            opts.on('-i', '--init', 'init config yml file from template.') do
                Helper.createDirIfNotExist("#{basePath}/latestCheckTimestamp/")
                Helper.createDirIfNotExist("#{basePath}/config/")

                configTemplateFolder = "#{File.expand_path("..", __dir__)}/config"
                appleSourceExampleYML = "#{configTemplateFolder}/apple.example.yml"
                androidSourceExampleYML = "#{configTemplateFolder}/android.example.yml"
                appleDestExampleYML = "#{basePath}/#{defaultConfigDirName}/#{defaultAppleConfigFileName}"
                androidDestExampleYML = "#{basePath}/#{defaultConfigDirName}/#{defaultAndroidConfigFileName}"
                
                if File.exists?(appleSourceExampleYML)
                    if File.exists?(appleDestExampleYML)
                        puts "Failed! Config YML File Exists: #{appleDestExampleYML}"
                    else
                        FileUtils.cp(appleSourceExampleYML, appleDestExampleYML)
                        puts "Init Apple Config YML File at:#{appleDestExampleYML} Success!"
                    end
                end
                #
                if File.exists?(androidSourceExampleYML)
                    if File.exists?(androidDestExampleYML)
                        puts "Failed! Config YML File Exists: #{androidDestExampleYML}"
                    else
                        FileUtils.cp(androidSourceExampleYML, androidDestExampleYML)
                        puts "Init Android Config YML File at:#{androidDestExampleYML} Success!"
                    end
                end

                checkLatestVersionOfZReviewTender()
            end
            
            opts.on('-n', '--new', 'update to latest version of ZReviewTender by RubyGem') do
                version = Version.new

                if version.getRemoteVersion() > version.getLocalVersion()
                    system('gem update ZReviewTender')
                else
                    puts "You're using the latest version of ZReviewTender!"
                end
            end

            opts.on('-v', '--versopm', 'show current version of ZReivewTender') do
                version = Version.new
                puts "Current ZReviewTender Version: #{version.getLocalVersion()}"

                checkLatestVersionOfZReviewTender()
            end
        end.parse!
    end

    private
    def checkLatestVersionOfZReviewTender()
        version = Version.new
        if version.getRemoteVersion() > version.getLocalVersion()
            puts "##########################################################"
            puts "#####           New Version Available!!!             #####"
            puts "#####  Please type `ZReviewTender -n` to update!!    #####"
            puts "##########################################################"
            puts "Local Verson: #{version.getLocalVersion()}"
            puts "Remote Verson: #{version.getRemoteVersion()}"
        end
    end

    private
    def configFileCheck(path, command)
        if !File.exists? path
            puts "Make sure you have vaild config file at #{path}"
            puts "Or use ZReviewTender #{command} specify config.yml file path"
            raise "Config file not found: #{path}"
        end
    end

    private
    def parseConfigYMLFile(configFilePath)
        configYMLObj = YAML.load_file(configFilePath)
        begin
            platform = Helper.unwrapRequiredParameter(configYMLObj, 'platform')
            
            fetcher = nil
            if platform.downcase == "apple"
                fetcher = AppleFetcher.new(AppleConfig.new(configYMLObj, configFilePath, ENV['PWD'] || ::Dir.pwd))
            elsif platform.downcase == "android"
                fetcher = AndroidFetcher.new(AndroidConfig.new(configYMLObj, configFilePath, ENV['PWD'] || ::Dir.pwd))
            else
                raise "unknow platform #{platform} in yml file #{configFilePath}."
            end

            processors = Helper.unwrapRequiredParameter(configYMLObj, 'processors')
            if processors.nil?
                processors = []
            end

            if processors.length < 1
                raise "must specify/enable at least one processor."
            end

            processors.each do |processor|
                processor.each do |key, value|
                    if value["enable"] != true
                        next
                    end
                    processorClass = Helper.unwrapRequiredParameter(value, "class")
                    require "Processors/#{processorClass}"
                    fetcher.registerProcessor(eval("#{processorClass}.new(#{value}, '#{configFilePath}', '#{ENV['PWD'] || ::Dir.pwd}')"))
                end
            end


            return fetcher
        rescue => e
            raise "#{e.message} in yml file #{configFilePath}."
        end        
    end
end

begin
    puts "#https://github.com/ZhgChgLi/ZReviewTender"
    puts "You have read and agree with the Disclaimer."
    puts "============================================"
    Main.new()
    puts "============================================"
    puts "Execute Successfully!!!"
    puts "#https://github.com/ZhgChgLi/ZReviewTender"
    puts "#Thanks for using this tool."
    puts "#If this is helpful, please help to star the repo or recommend it to your friends."
rescue => e
    logger = ZLogger.new(ENV['PWD'] || ::Dir.pwd)
    title = "#Error: #{e.class} #{e.message}"
    body = e.backtrace
    
    logger.logError("===RUNTIME EXCEPTION START===")
    logger.logError(title)
    logger.logError(body)
    logger.logError("===RUNTIME EXCEPTION END===")
        
    puts title
    puts body
end
