// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (c) 2012-2014 Monty Program Ab
// Copyright (c) 2015-2021 MariaDB Corporation Ab

package org.mariadb.jdbc.plugin.codec;

import java.io.IOException;
import java.sql.SQLDataException;
import java.time.Duration;
import java.util.Calendar;
import java.util.EnumSet;
import org.mariadb.jdbc.client.*;
import org.mariadb.jdbc.client.socket.Writer;
import org.mariadb.jdbc.plugin.Codec;

/** Duration codec */
public class DurationCodec implements Codec<Duration> {

  /** default instance */
  public static final DurationCodec INSTANCE = new DurationCodec();

  private static final EnumSet<DataType> COMPATIBLE_TYPES =
      EnumSet.of(
          DataType.TIME,
          DataType.DATETIME,
          DataType.TIMESTAMP,
          DataType.VARSTRING,
          DataType.VARCHAR,
          DataType.STRING,
          DataType.BLOB,
          DataType.TINYBLOB,
          DataType.MEDIUMBLOB,
          DataType.LONGBLOB);

  public String className() {
    return Duration.class.getName();
  }

  public boolean canDecode(ColumnDecoder column, Class<?> type) {
    return COMPATIBLE_TYPES.contains(column.getType()) && type.isAssignableFrom(Duration.class);
  }

  public boolean canEncode(Object value) {
    return value instanceof Duration;
  }

  @Override
  @SuppressWarnings("fallthrough")
  public Duration decodeText(ReadableByteBuf buf, int length, ColumnDecoder column, Calendar cal)
      throws SQLDataException {

    int[] parts;
    switch (column.getType()) {
      case TIMESTAMP:
      case DATETIME:
        parts = LocalDateTimeCodec.parseTimestamp(buf.readAscii(length));
        if (parts == null) return null;
        return Duration.ZERO
            .plusDays(parts[2] - 1)
            .plusHours(parts[3])
            .plusMinutes(parts[4])
            .plusSeconds(parts[5])
            .plusNanos(parts[6]);

      case BLOB:
      case TINYBLOB:
      case MEDIUMBLOB:
      case LONGBLOB:
        if (column.isBinary()) {
          buf.skip(length);
          throw new SQLDataException(
              String.format("Data type %s cannot be decoded as Duration", column.getType()));
        }
        // expected fallthrough
        // BLOB is considered as String if it has a collation (this is TEXT column)

      case TIME:
      case VARCHAR:
      case VARSTRING:
      case STRING:
        parts = LocalTimeCodec.parseTime(buf, length, column);
        Duration d =
            Duration.ZERO
                .plusHours(parts[1])
                .plusMinutes(parts[2])
                .plusSeconds(parts[3])
                .plusNanos(parts[4]);
        if (parts[0] == -1) return d.negated();
        return d;

      default:
        buf.skip(length);
        throw new SQLDataException(
            String.format("Data type %s cannot be decoded as Duration", column.getType()));
    }
  }

  @Override
  @SuppressWarnings("fallthrough")
  public Duration decodeBinary(ReadableByteBuf buf, int length, ColumnDecoder column, Calendar cal)
      throws SQLDataException {

    long days = 0;
    int hours = 0;
    int minutes = 0;
    int seconds = 0;
    long microseconds = 0;
    switch (column.getType()) {
      case TIME:
        boolean negate = false;
        if (length > 0) {
          negate = buf.readUnsignedByte() == 0x01;
          if (length > 4) {
            days = buf.readUnsignedInt();
            if (length > 7) {
              hours = buf.readByte();
              minutes = buf.readByte();
              seconds = buf.readByte();
              if (length > 8) {
                microseconds = buf.readInt();
              }
            }
          }
        }

        Duration duration =
            Duration.ZERO
                .plusDays(days)
                .plusHours(hours)
                .plusMinutes(minutes)
                .plusSeconds(seconds)
                .plusNanos(microseconds * 1000);
        if (negate) return duration.negated();
        return duration;

      case TIMESTAMP:
      case DATETIME:
        if (length == 0) return null;
        int year = buf.readUnsignedShort();
        int month = buf.readByte();
        days = buf.readByte();
        if (length > 4) {
          hours = buf.readByte();
          minutes = buf.readByte();
          seconds = buf.readByte();

          if (length > 7) {
            microseconds = buf.readUnsignedInt();
          }
        }

        // xpand workaround https://jira.mariadb.org/browse/XPT-274
        if (year == 0 && month == 0 && days == 0 && hours == 0 && minutes == 0 && seconds == 0)
          return null;

        return Duration.ZERO
            .plusDays(days - 1)
            .plusHours(hours)
            .plusMinutes(minutes)
            .plusSeconds(seconds)
            .plusNanos(microseconds * 1000);

      case VARCHAR:
      case VARSTRING:
      case STRING:
        int[] parts = LocalTimeCodec.parseTime(buf, length, column);
        Duration d =
            Duration.ZERO
                .plusHours(parts[1])
                .plusMinutes(parts[2])
                .plusSeconds(parts[3])
                .plusNanos(parts[4]);
        if (parts[0] == -1) return d.negated();
        return d;

      default:
        buf.skip(length);
        throw new SQLDataException(
            String.format("Data type %s cannot be decoded as Duration", column.getType()));
    }
  }

  @Override
  public void encodeText(Writer encoder, Context context, Object val, Calendar cal, Long maxLen)
      throws IOException {
    long s = ((Duration) val).getSeconds();
    long microSecond = ((Duration) val).getNano() / 1000;
    encoder.writeByte('\'');
    if (microSecond != 0) {
      encoder.writeAscii(
          String.format("%d:%02d:%02d.%06d", s / 3600, (s % 3600) / 60, (s % 60), microSecond));
    } else {
      encoder.writeAscii(String.format("%d:%02d:%02d", s / 3600, (s % 3600) / 60, (s % 60)));
    }
    encoder.writeByte('\'');
  }

  @Override
  public void encodeBinary(Writer encoder, Object val, Calendar cal, Long maxLength)
      throws IOException {
    int nano = ((Duration) val).getNano();
    if (nano > 0) {
      encoder.writeByte((byte) 12);
      encodeDuration(encoder, ((Duration) val));
      encoder.writeInt(nano / 1000);
    } else {
      encoder.writeByte((byte) 8);
      encodeDuration(encoder, ((Duration) val));
    }
  }

  private void encodeDuration(Writer encoder, Duration value) throws IOException {
    encoder.writeByte((byte) (value.isNegative() ? 1 : 0));
    encoder.writeInt((int) value.toDays());
    encoder.writeByte((byte) (value.toHours() - 24 * value.toDays()));
    encoder.writeByte((byte) (value.toMinutes() - 60 * value.toHours()));
    encoder.writeByte((byte) (value.getSeconds() - 60 * value.toMinutes()));
  }

  public int getBinaryEncodeType() {
    return DataType.TIME.get();
  }
}
