# frozen_string_literal: true

module RubyNext
  module Language
    module Rewriters
      class RightHandAssignment < Base
        NAME = "right-hand-assignment"
        SYNTAX_PROBE = "1 + 2 => a"
        MIN_SUPPORTED_VERSION = Gem::Version.new("3.0.0")

        def on_rasgn(node)
          context.track! self

          node = super(node)

          val_node, asgn_node = *node

          remove(val_node.loc.expression.end.join(asgn_node.loc.expression))
          insert_before(val_node.loc.expression, "#{asgn_node.loc.expression.source} = ")

          asgn_node.updated(
            nil,
            asgn_node.children + [val_node]
          )
        end

        def on_vasgn(node)
          return super(node) unless rightward?(node)

          context.track! self

          name, val_node = *node

          remove(val_node.loc.expression.end.join(node.loc.name))
          insert_before(val_node.loc.expression, "#{name} = ")

          super(node)
        end

        def on_casgn(node)
          return super(node) unless rightward?(node)

          context.track! self

          scope_node, name, val_node = *node

          if scope_node
            scope = scope_node.type == :cbase ? scope_node.loc.expression.source : "#{scope_node.loc.expression.source}::"
            name = "#{scope}#{name}"
          end

          remove(val_node.loc.expression.end.join(node.loc.name))
          insert_before(val_node.loc.expression, "#{name} = ")

          super(node)
        end

        def on_mrasgn(node)
          context.track! self

          node = super(node)

          lhs, rhs = *node

          replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
          insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")

          node.updated(
            :masgn,
            [rhs, lhs]
          )
        end

        def on_masgn(node)
          return super(node) unless rightward?(node)

          context.track! self

          rhs, lhs = *node

          replace(lhs.loc.expression.end.join(rhs.loc.expression), ")")
          insert_before(lhs.loc.expression, "#{rhs.loc.expression.source} = (")

          node = super(node)

          lhs, rhs = *node

          node.updated(
            nil,
            [
              lhs,
              s(:begin, rhs)
            ]
          )
        end

        private

        def rightward?(node)
          # Location could be empty for node built by rewriters
          return false unless ((!node.loc.nil? || nil) && node.loc.operator)

          assignee_loc =
            if node.type == :masgn
              node.children[0].loc.expression
            else
              node.loc.name
            end

          return false unless assignee_loc

          assignee_loc.begin_pos > node.loc.operator.end_pos
        end
      end
    end
  end
end