package prolog.ast.terms

import prolog.Answers
import prolog.Substitutions
import prolog.ast.logic.Resolvent
import prolog.logic.applySubstitution
import prolog.logic.unifyLazy
import prolog.ast.arithmetic.Integer

typealias Argument = Term

typealias CompoundTerm = Structure

open class Structure(val name: Atom, var arguments: List<Argument>) : Goal(), Head, Body, Resolvent {
    constructor(name: String, vararg arguments: Argument) : this(Atom(name), arguments.asList())

    override val functor: Functor = Functor(name, Integer(arguments.size))

    override fun solve(goal: Goal, subs: Substitutions): Answers {
        return unifyLazy(goal, this, subs)
    }

    override fun toString(): String {
        return when {
            arguments.isEmpty() -> name.name
            else -> "${name.name}(${arguments.joinToString(",")})"
        }
    }

    override fun applySubstitution(subs: Substitutions): Structure = Structure(
        name,
        arguments.map { applySubstitution(it, subs) }
    )

    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (other !is Structure) return false
        if (functor != other.functor) return false
        return arguments.zip(other.arguments).all { (a, b) -> a == b }
    }

    override fun hashCode(): Int {
        return javaClass.hashCode()
    }
}
