class CreateShixunService < ApplicationService
  attr_reader :user, :params, :permit_params

  def initialize(user, permit_params, params)
    @user   = user
    @params = params
    @permit_params = permit_params
  end

  def call
    shixun = Shixun.new(permit_params)
    identifier = Util::UUID.generate_identifier(Shixun, 8)
    shixun.identifier= identifier
    shixun.user_id = user.id
    main_mirror = MirrorRepository.find params[:main_type]
    sub_mirrors = MirrorRepository.where(id: params[:sub_type])
    begin
      ActiveRecord::Base.transaction do
        shixun.save!
        # 获取脚本内容
        shixun_script = get_shixun_script(shixun, main_mirror, sub_mirrors)
        # 创建额外信息
        ShixunInfo.create!(shixun_id: shixun.id, evaluate_script: shixun_script, description: params[:description])
        # 创建合作者
        shixun.shixun_members.create!(user_id: user.id, role: 1)
        # 创建镜像
        ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => main_mirror.id)
        # 创建主服务配置
        config_params =
            if shixun.is_jupyter?
              {shixun_id: shixun.id, mirror_repository_id: main_mirror.id, cpu_limit: 2,
               memory_limit: 1024, lower_cpu_limit: 0.2, request_limit: 100}
            else
              {shixun_id: shixun.id, mirror_repository_id: main_mirror.id}
            end
        ShixunServiceConfig.create!(config_params)
        # 创建子镜像相关数据(实训镜像关联表,子镜像服务配置)
        sub_mirrors.each do |sub|
          ShixunMirrorRepository.create!(:shixun_id => shixun.id, :mirror_repository_id => sub.id)
          # 实训子镜像服务配置
          name = sub.name #查看镜像是否有名称,如果没有名称就不用服务配置
          ShixunServiceConfig.create!(:shixun_id => shixun.id, :mirror_repository_id => sub.id) if name.present?
        end
        # 创建版本库
        repo_path = repo_namespace(user.login, shixun.identifier)
        GitService.add_repository(repo_path: repo_path)
        shixun.update_column(:repo_name, repo_path.split(".")[0])
        # 如果是云上实验室,创建相关记录
        if !Laboratory.current.main_site?
          Laboratory.current.laboratory_shixuns.create!(shixun: shixun, ownership: true)
        end
        # 如果是jupyter,先创建一个目录,为了挂载(因为后续数据集,开启Pod后环境在没销毁前,你上传数据集是挂载不上目录的,因此要先创建目录,方便中间层挂载)
        if shixun.is_jupyter?
          folder = EduSetting.get('shixun_folder')
          path = "#{folder}/#{identifier}"
          FileUtils.mkdir_p(path, :mode => 0777) unless File.directory?(path)
        end
        return shixun
      end
    rescue => e
      Rails.logger.error("shixun_create_error: #{e.message}")
      raise("创建实训失败!")
    end
  end

  private

  def get_shixun_script shixun, main_mirror, sub_mirrors
    if !shixun.is_jupyter?
      mirror = main_mirror.mirror_scripts
      if main_mirror.blank?
        modify_shixun_script shixun, mirror.first&.(:script)
      else
        sub_name = sub_mirrors.pluck(:type_name)
        if main_mirror.type_name == "Java" && sub_name.include?("Mysql")
          mirror.last.try(:script)
        else
          shixun_script = mirror.first&.script
          modify_shixun_script shixun, shixun_script
        end
      end
    end
  end

  def modify_shixun_script shixun, script
    if script.present?
      source_class_name = []
      challenge_program_name = []
      shixun.challenges.map(&:exec_path).each do |exec_path|
        challenge_program_name << "\"#{exec_path}\""
        if shixun.main_mirror_name == "Java"
          if exec_path.nil? || exec_path.split("src/")[1].nil?
            source = "\"\""
          else
            source = "\"#{exec_path.split("src/")[1].split(".java")[0]}\""
          end
          logger.info("----source: #{source}")
          source_class_name << source.gsub("/", ".") if source.present?
        elsif shixun.main_mirror_name.try(:first) == "C#"
          if exec_path.nil? || exec_path.split(".")[1].nil?
            source = "\"\""
          else
            source = "\"#{exec_path.split(".")[0]}.exe\""
          end
          source_class_name << source if source.present?
        end
      end
      script = if script.include?("sourceClassName") && script.include?("challengeProgramName")
                 script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{source_class_name.reject(&:blank?).join(" ")}\)")
               else
                 script.gsub(/challengeProgramNames=\(.*\)/,"challengeProgramNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)").gsub(/sourceClassNames=\(.*\)/, "sourceClassNames=\(#{challenge_program_name.reject(&:blank?).join(" ")}\)")
               end
    end
    return script
  end

  # 版本库目录空间
  def repo_namespace(user, shixun_identifier)
    "#{user}/#{shixun_identifier}.git"
  end

end