module EacLauncher
  module Stereotypes
    class GitSubrepo
      class Warp < ::EacLauncher::Paths::Real
        include ::Eac::SimpleCache

        attr_reader :instance

        def initialize(instance)
          @instance = instance
          check_parent
          init_aux
          push_to_aux
          reset
          assert_target_remote
          super(cache_git)
        end

        private

        def check_parent
          return if parent_cache_git.rev_parse(subrepo_parent_hash) &&
                    parent_cache_git.descendant?('HEAD', subrepo_parent_hash)
          raise EacLauncher::Instances::Error, "Subrepo parent hash \"#{subrepo_parent_hash}\""\
            " not found in \"#{parent_cache_git}\""
        end

        def subrepo_parent_hash
          data = parent_cache_git.subrepo_status(instance.to_parent_path)
          h = data['Pull Parent']
          return h if h.present?
          raise EacLauncher::Instances::Error, "Subrepo parent hash is blank: #{data}"
        end

        def init_aux
          ::EacLauncher::Git::Base.new(aux_path).init_bare
        end

        def parent_instance
          instance.parent
        end

        def parent_git_uncached
          ::EacLauncher::Git::Base.new(parent_instance.real)
        end

        def parent_cache_git_uncached
          ::EacLauncher::Git::Base.new(parent_instance.warped)
        end

        def aux_path
          instance.cache_path('subrepo_aux_git_repository')
        end

        def cache_git_uncached
          ::EacLauncher::Git::Base.new(instance.cache_path('git_repository'))
        end

        def push_to_aux
          parent_cache_git.execute!('subrepo', 'branch', subrepo_subdir, '-fF')
          h = parent_cache_git.rev_parse("subrepo/#{subrepo_subdir}", true)
          parent_cache_git.execute!('push', aux_path, "#{h}:refs/heads/master", '--force')
        end

        def subrepo_subdir
          instance.to_parent_path.gsub(%r{\A/+}, '')
        end

        def reset
          ::EacLauncher::Git::MirrorUpdate.new(cache_git, aux_path, 'master')
        end

        def assert_target_remote
          cache_git.assert_remote_url(::EacLauncher::Git::WarpBase::TARGET_REMOTE,
                                      target_remote_url)
        end

        def target_remote_url
          ::EacLauncher::Vendor::Github.to_ssh_url(
            parent_cache_git.subrepo_remote_url(subrepo_subdir)
          )
        end
      end
    end
  end
end