#!/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?("#{basePath}/latestCheckTimestamp/.keep")
                    File.open("#{basePath}/latestCheckTimestamp/.keep", 'w') { |file| file.write("") }
                end
                #
                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('-d', '--delete', 'delete latest check timestamp log file.(factory reset)') do
                FileUtils.rm_rf("#{basePath}/latestCheckTimestamp/")
                Helper.createDirIfNotExist("#{basePath}/latestCheckTimestamp/")
                if !File.exists?("#{basePath}/latestCheckTimestamp/.keep")
                    File.open("#{basePath}/latestCheckTimestamp/.keep", 'w') { |file| file.write("") }
                end

                puts "Clean all  latest check timestamp log file in /latestCheckTimestamp success."
            end

            opts.on('-v', '--version', '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)
        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  
    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)
    errorMessage = "#Error Message:  #{e.message}\n"
    errorMessage += "#Error Class: #{e.class}\n"
    errorMessage += "#Backtrace Start#\n#{e.backtrace.join("\n")}\n#Backtrace End#\n"
    logger.logError(errorMessage)

    puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    puts "XXXXX  Excute Failed, Error Occurred!  XXXXX"
    puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
    puts "X https://github.com/ZhgChgLi/ZReviewTender"
    puts "X Please create an issue on above repo, and provide error log, thanks!"
    puts "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

    raise e
end
