// 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.util.Calendar;
import org.mariadb.jdbc.client.*;
import org.mariadb.jdbc.client.socket.Writer;
import org.mariadb.jdbc.plugin.Codec;
import org.mariadb.jdbc.type.*;

/** GeometryCollection codec */
public class GeometryCollectionCodec implements Codec<GeometryCollection> {

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

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

  public boolean canDecode(ColumnDecoder column, Class<?> type) {
    return column.getType() == DataType.GEOMETRY && type.isAssignableFrom(GeometryCollection.class);
  }

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

  @Override
  public GeometryCollection decodeText(
      ReadableByteBuf buf, int length, ColumnDecoder column, Calendar cal) throws SQLDataException {
    return decodeBinary(buf, length, column, cal);
  }

  @Override
  public GeometryCollection decodeBinary(
      ReadableByteBuf buf, int length, ColumnDecoder column, Calendar cal) throws SQLDataException {
    if (column.getType() == DataType.GEOMETRY) {
      buf.skip(4); // SRID
      Geometry geo = Geometry.getGeometry(buf, length - 4, column);
      if (geo instanceof GeometryCollection) return (GeometryCollection) geo;
      throw new SQLDataException(
          String.format(
              "Geometric type %s cannot be decoded as GeometryCollection",
              geo.getClass().getName()));
    }
    buf.skip(length);
    throw new SQLDataException(
        String.format("Data type %s cannot be decoded as GeometryCollection", column.getType()));
  }

  @Override
  public void encodeText(
      Writer encoder, Context context, Object value, Calendar cal, Long maxLength)
      throws IOException {
    encoder.writeBytes(("ST_GeomCollFromText('" + value.toString() + "')").getBytes());
  }

  @Override
  public void encodeBinary(Writer encoder, Object value, Calendar cal, Long maxLength)
      throws IOException {
    GeometryCollection geometryCollection = (GeometryCollection) value;

    int length = 13;
    for (Geometry geo : geometryCollection.getGeometries()) {
      if (geo instanceof Point) {
        length += 21;
      } else if (geo instanceof LineString) {
        length += 9 + ((LineString) geo).getPoints().length * 16;
      } else if (geo instanceof Polygon) {
        length += 9;
        for (LineString ls : ((Polygon) geo).getLines()) {
          length += 4 + ls.getPoints().length * 16;
        }
      } else if (geo instanceof MultiPoint) {
        length += 9 + ((MultiPoint) geo).getPoints().length * 21;
      } else if (geo instanceof MultiLineString) {
        length += 9;
        for (LineString ls : ((MultiLineString) geo).getLines()) {
          length += 9 + ls.getPoints().length * 16;
        }
      } else if (geo instanceof MultiPolygon) {
        length += 9;
        for (Polygon poly : ((MultiPolygon) geo).getPolygons()) {
          length += 9;
          for (LineString ls : poly.getLines()) {
            length += 4 + ls.getPoints().length * 16;
          }
        }
      }
    }

    encoder.writeLength(length);
    encoder.writeInt(0); // SRID
    encoder.writeByte(0x01); // LITTLE ENDIAN
    encoder.writeInt(7); // wkbGeometryCollection
    encoder.writeInt(geometryCollection.getGeometries().length);
    for (Geometry geo : geometryCollection.getGeometries()) {
      if (geo instanceof Point) {
        Point pt = (Point) geo;
        encoder.writeByte(0x01); // LITTLE ENDIAN
        encoder.writeInt(1); // wkbPoint
        encoder.writeDouble(pt.getX());
        encoder.writeDouble(pt.getY());
      } else if (geo instanceof LineString) {
        LineString ls = (LineString) geo;
        encoder.writeByte(0x01); // LITTLE ENDIAN
        encoder.writeInt(2); // wkbLineString
        encoder.writeInt(ls.getPoints().length);
        for (Point pt : ls.getPoints()) {
          encoder.writeDouble(pt.getX());
          encoder.writeDouble(pt.getY());
        }
      } else if (geo instanceof Polygon) {
        Polygon poly = (Polygon) geo;
        encoder.writeByte(0x01); // LITTLE ENDIAN
        encoder.writeInt(3); // wkbPolygon
        encoder.writeInt(poly.getLines().length);
        for (LineString ls : poly.getLines()) {
          encoder.writeInt(ls.getPoints().length);
          for (Point pt : ls.getPoints()) {
            encoder.writeDouble(pt.getX());
            encoder.writeDouble(pt.getY());
          }
        }
      } else if (geo instanceof MultiPoint) {
        MultiPoint mp = (MultiPoint) geo;
        encoder.writeByte(0x01); // LITTLE ENDIAN
        encoder.writeInt(4); // wkbMultiPoint
        encoder.writeInt(mp.getPoints().length);
        for (Point pt : mp.getPoints()) {
          encoder.writeByte(0x01); // LITTLE ENDIAN
          encoder.writeInt(1); // wkbPoint
          encoder.writeDouble(pt.getX());
          encoder.writeDouble(pt.getY());
        }
      } else if (geo instanceof MultiLineString) {
        MultiLineString mlines = (MultiLineString) geo;
        encoder.writeByte(0x01); // LITTLE ENDIAN
        encoder.writeInt(5); // wkbMultiLineString
        encoder.writeInt(mlines.getLines().length);
        for (LineString ls : mlines.getLines()) {
          encoder.writeByte(0x01); // LITTLE ENDIAN
          encoder.writeInt(2); // wkbLineString
          encoder.writeInt(ls.getPoints().length); // nb points
          for (Point pt : ls.getPoints()) {
            encoder.writeDouble(pt.getX());
            encoder.writeDouble(pt.getY());
          }
        }
      } else if (geo instanceof MultiPolygon) {
        MultiPolygon multiPolygon = (MultiPolygon) geo;
        encoder.writeByte(0x01); // LITTLE ENDIAN
        encoder.writeInt(6); // wkbMultiPolygon
        encoder.writeInt(multiPolygon.getPolygons().length); // nb polygon

        for (Polygon poly : multiPolygon.getPolygons()) {
          encoder.writeByte(0x01); // LITTLE ENDIAN
          encoder.writeInt(3); // wkbPolygon
          encoder.writeInt(poly.getLines().length);
          for (LineString ls : poly.getLines()) {
            encoder.writeInt(ls.getPoints().length);
            for (Point pt : ls.getPoints()) {
              encoder.writeDouble(pt.getX());
              encoder.writeDouble(pt.getY());
            }
          }
        }
      }
    }
  }

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