package liquibase.database.typeconversion.core;

import liquibase.database.Database;
import liquibase.database.core.PostgresDatabase;
import liquibase.database.structure.type.BlobType;
import liquibase.database.structure.type.ClobType;
import liquibase.database.structure.type.DateTimeType;
import liquibase.database.structure.type.DataType;

import java.text.ParseException;
import java.sql.Types;

public class PostgresTypeConverter extends AbstractTypeConverter {

    public int getPriority() {
        return PRIORITY_DATABASE;
    }

    public boolean supports(Database database) {
        return database instanceof PostgresDatabase;
    }


    @Override
    public Object convertDatabaseValueToObject(Object defaultValue, int dataType, int columnSize, int decimalDigits, Database database) throws ParseException {
        if (defaultValue != null) {
            if (defaultValue instanceof String) {
                defaultValue = ((String) defaultValue).replaceAll("'::[\\w\\s]+$", "'");

                if (dataType == Types.DATE || dataType == Types.TIME || dataType == Types.TIMESTAMP) {
                    //remove trailing time zone info
                    defaultValue = ((String) defaultValue).replaceFirst("-\\d+$", "");
                }
            }
        }
        return super.convertDatabaseValueToObject(defaultValue, dataType, columnSize, decimalDigits, database);

    }

    @Override
    public DataType getDataType(String columnTypeString, Boolean autoIncrement) {
        DataType type = super.getDataType(columnTypeString, autoIncrement);

        if (type.getDataTypeName().startsWith("TEXT(")) {
            type = getClobType();
        } else if (type.getDataTypeName().toLowerCase().startsWith("float8")) {
            type.setDataTypeName("FLOAT8");
        } else if (type.getDataTypeName().toLowerCase().startsWith("float4")) {
            type.setDataTypeName("FLOAT4");
        }


        if (autoIncrement != null && autoIncrement) {
            if ("integer".equals(type.getDataTypeName().toLowerCase())) {
                type.setDataTypeName("serial");
            } else if ("bigint".equals(type.getDataTypeName().toLowerCase()) || "bigserial".equals(type.getDataTypeName().toLowerCase())) {
                type.setDataTypeName("bigserial");
            } else {
                // Unknown integer type, default to "serial"
                type.setDataTypeName("serial");
            }
        }

        return type;
    }


    @Override
    protected Object convertToCorrectObjectType(String value, int dataType, int columnSize, int decimalDigits, Database database) throws ParseException {
        Object returnValue = super.convertToCorrectObjectType(value, dataType, columnSize, decimalDigits, database);
        if (returnValue != null && returnValue instanceof String) {
            if (((String) returnValue).startsWith("NULL::")) {
                return null;
            }
        }
        return returnValue;
    }

    @Override
    public ClobType getClobType() {
        return new ClobType("TEXT");
    }

    @Override
    public BlobType getBlobType() {
        return new BlobType("BYTEA");
    }

    @Override
    public DateTimeType getDateTimeType() {
        return new DateTimeType("TIMESTAMP WITH TIME ZONE");
    }
}

@@ -176,176 +176,9 @@
 ype.
-BlobType;%0D%0Aimport liquibase.database.structure.type.ClobType;%0D%0Aimport liquibase.database.structure.type.DateTimeType;%0D%0Aimport liquibase.database.structure.type.DataType
+*
 ;%0D%0A%0D
@@ -3216,12 +3216,120 @@
 %0D%0A    %7D%0D
+%0A%0D%0A    @Override%0D%0A    public NumberType getNumberType() %7B%0D%0A        return new NumberType(%22NUMERIC%22);%0D%0A    %7D%0D
 %0A%7D%0D%0A

support numberType for postgres