package de.dhbwstuttgart.syntaxtree.type;

import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.server.packet.dataContainers.ISerializableData;
import de.dhbwstuttgart.server.packet.dataContainers.KeyStorage;
import de.dhbwstuttgart.server.packet.dataContainers.serialized.SerialMap;
import de.dhbwstuttgart.syntaxtree.ASTVisitor;
import de.dhbwstuttgart.typeinference.result.ResultSetVisitor;
import de.dhbwstuttgart.typeinference.unify.UnifyContext;
import org.antlr.v4.runtime.Token;

import java.util.Objects;

public class GenericRefType extends RefTypeOrTPHOrWildcardOrGeneric implements ISerializableData {
  private String name;

  public GenericRefType(String name, Token offset) {
    super(offset);
    this.name = name;
  }

  public String getParsedName() {
    return name.toString();
  }

  @Override
  public void accept(ASTVisitor visitor) {
    visitor.visit(this);
  }

  @Override
  public <A> A acceptTV(TypeVisitor<A> visitor) {
    return visitor.visit(this);
  }

  @Override
  public void accept(ResultSetVisitor visitor) {
    visitor.visit(this);
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    GenericRefType that = (GenericRefType) o;
    return name.equals(that.name);
  }

  @Override
  public int hashCode() {
    return Objects.hash(name);
  }

  @Override
  public String toString() {
    return "GTV " + this.name;
  }

  @Override
  public SerialMap toSerial(KeyStorage keyStorage) {
    SerialMap serialized = new SerialMap();
    serialized.put("name", this.name);

    // create the wrapper and put this as the object
    var serializedWrapper = super.toSerial(keyStorage).assertType(SerialMap.class);
    serializedWrapper.put("object", serialized);
    return serializedWrapper;
  }

  public static GenericRefType fromSerial(SerialMap data, UnifyContext context) {
    return new GenericRefType(
      data.getValue("name").getOf(String.class),
      new NullToken()
    );
  }
}

