package com.oguerreiro.resilient.domain.usertype;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;

import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.usertype.ParameterizedType;
import org.hibernate.usertype.UserType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.oguerreiro.resilient.activity.registry.ActivityProgressDescriptor;
import com.oguerreiro.resilient.activity.registry.ActivityProgressRegistry;

@Component
public class ActivityProgressUserType implements UserType<String>, ParameterizedType {

  @Autowired
  private ActivityProgressRegistry activityProgressRegistry;

  private String domainClassName;

  @Override
  public int getSqlType() {
    return Types.VARCHAR;
  }

  @Override
  public Class<String> returnedClass() {
    return String.class;
  }

  @Override
  public boolean equals(String x, String y) {
    return x == y || (x != null && x.equals(y));
  }

  @Override
  public int hashCode(String x) {
    return x.hashCode();
  }

  @Override
  public String nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner)
      throws SQLException {
    String id = rs.getString(position);

    if (id == null || id.trim().length() == 0)
      return null;

    ActivityProgressDescriptor apd = this.activityProgressRegistry.progressOf(this.domainClassName + "@" + id);
    if (apd == null)
      return null;

    if (apd.getProgressPercentage() >= 100)
      return null;

    return apd.getProgressPercentage().toString();
  }

  @Override
  public void nullSafeSet(PreparedStatement st, String value, int index, SharedSessionContractImplementor session)
      throws SQLException {
    // TODO Auto-generated method stub
    // IGNORE. This is a virtual property READONLY.
  }

  @Override
  public String deepCopy(String value) {
    return value;
  }

  @Override
  public boolean isMutable() {
    return true;
  }

  @Override
  public Serializable disassemble(String value) {
    return (Serializable) deepCopy(value);
  }

  @Override
  public String assemble(Serializable cached, Object owner) {
    return (String) cached;
  }

  @Override
  public void setParameterValues(Properties parameters) {
    this.domainClassName = parameters.getProperty("activityDomainClass");
  }

}
