/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.olingo.commons.core.edm.primitivetype;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.edm.geo.ComposedGeospatial;
import org.apache.olingo.commons.api.edm.geo.Geospatial;
import org.apache.olingo.commons.api.edm.geo.Geospatial.Dimension;
import org.apache.olingo.commons.api.edm.geo.Geospatial.Type;
import org.apache.olingo.commons.api.edm.geo.GeospatialCollection;
import org.apache.olingo.commons.api.edm.geo.LineString;
import org.apache.olingo.commons.api.edm.geo.MultiLineString;
import org.apache.olingo.commons.api.edm.geo.MultiPoint;
import org.apache.olingo.commons.api.edm.geo.MultiPolygon;
import org.apache.olingo.commons.api.edm.geo.Point;
import org.apache.olingo.commons.api.edm.geo.Polygon;
import org.apache.olingo.commons.api.edm.geo.SRID;

public abstract class AbstractGeospatialType<T extends Geospatial> extends SingletonPrimitiveType {

  private static final Pattern PATTERN =
      Pattern.compile("([a-z]+)'SRID=([0-9]+);([a-zA-Z]+)\\((.*)\\)'");

  private static final Pattern COLLECTION_PATTERN =
      Pattern.compile("([a-z]+)'SRID=([0-9]+);Collection\\(([a-zA-Z]+)\\((.*)\\)\\)'");

  private final Class<T> reference;

  protected final Dimension dimension;

  protected final Type type;

  protected AbstractGeospatialType(final Class<T> reference, final Dimension dimension, final Type type) {
    this.reference = reference;
    this.dimension = dimension;
    this.type = type;
  }

  @Override
  public Class<?> getDefaultType() {
    return reference;
  }

  private Matcher getMatcher(final Pattern pattern, final String value) throws EdmPrimitiveTypeException {
    final Matcher matcher = pattern.matcher(value);
    if (!matcher.matches()) {
      throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
    }

    Geospatial.Dimension _dimension = null;
    Geospatial.Type _type = null;
    try {
      _dimension = Geospatial.Dimension.valueOf(matcher.group(1).toUpperCase());
      _type = Geospatial.Type.valueOf(matcher.group(3).toUpperCase());
    } catch (IllegalArgumentException e) {
      throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.", e);
    }
    if (_dimension != this.dimension || (!pattern.equals(COLLECTION_PATTERN) && _type != this.type)) {
      throw new EdmPrimitiveTypeException("The literal '" + value + "' has illegal content.");
    }

    return matcher;
  }

  private Point newPoint(final SRID srid, final String point, final Boolean isNullable,
      final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode)
          throws EdmPrimitiveTypeException {

    final List<String> pointCoo = split(point, ' ');
    if (pointCoo == null || pointCoo.size() != 2) {
      throw new EdmPrimitiveTypeException("The literal '" + point + "' has illegal content.");
    }

    final Point result = new Point(this.dimension, srid);
    result.setX(EdmDouble.getInstance().valueOfString(pointCoo.get(0),
        isNullable, maxLength, precision, scale, isUnicode, Double.class));
    result.setY(EdmDouble.getInstance().valueOfString(pointCoo.get(1),
        isNullable, maxLength, precision, scale, isUnicode, Double.class));

    return result;
  }

  protected Point stringToPoint(final String value, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    final Matcher matcher = getMatcher(PATTERN, value);

    return newPoint(SRID.valueOf(matcher.group(2)), matcher.group(4),
        isNullable, maxLength, precision, scale, isUnicode);
  }

  protected MultiPoint stringToMultiPoint(final String value, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    final Matcher matcher = getMatcher(PATTERN, value);

    final List<Point> points = new ArrayList<>();
    for (final String pointCoo : split(matcher.group(4), ',')) {
      points.add(newPoint(null, pointCoo.substring(1, pointCoo.length() - 1),
          isNullable, maxLength, precision, scale, isUnicode));
    }

    return new MultiPoint(dimension, SRID.valueOf(matcher.group(2)), points);
  }

  private LineString newLineString(final SRID srid, final String lineString, final Boolean isNullable,
      final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode)
          throws EdmPrimitiveTypeException {

    final List<Point> points = new ArrayList<>();
    for (final String pointCoo : split(lineString, ',')) {
      points.add(newPoint(null, pointCoo, isNullable, maxLength, precision, scale, isUnicode));
    }

    return new LineString(this.dimension, srid, points);
  }

  protected LineString stringToLineString(final String value, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    final Matcher matcher = getMatcher(PATTERN, value);

    return newLineString(SRID.valueOf(matcher.group(2)), matcher.group(4),
        isNullable, maxLength, precision, scale, isUnicode);
  }

  protected MultiLineString stringToMultiLineString(final String value, final Boolean isNullable,
      final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode)
          throws EdmPrimitiveTypeException {

    final Matcher matcher = getMatcher(PATTERN, value);

    final List<LineString> lineStrings = new ArrayList<>();
    for (String coo : matcher.group(4).contains("),(")
        ? matcher.group(4).split("\\),\\(") : new String[] { matcher.group(4) }) {

      String lineString = coo;
      if (lineString.charAt(0) == '(') {
        lineString = lineString.substring(1);
      }
      if (lineString.endsWith(")")) {
        lineString = lineString.substring(0, lineString.length() - 1);
      }

      lineStrings.add(newLineString(null, lineString, isNullable, maxLength, precision, scale, isUnicode));
    }

    return new MultiLineString(this.dimension, SRID.valueOf(matcher.group(2)), lineStrings);
  }

  private Polygon newPolygon(final SRID srid, final String polygon, final Boolean isNullable,
      final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode)
          throws EdmPrimitiveTypeException {

    final String[] first = polygon.split("\\),\\(");

    final List<LineString> interiorRings = new ArrayList<>();
    for (int i = 0; i < first.length -1; i++) {
    	List<Point> interior = new ArrayList<Point>();
	    for (final String pointCoo : split(first[i].substring(i==0?1:0, first[i].length()), ',')) {
	      interior.add(newPoint(null, pointCoo, isNullable, maxLength, precision, scale, isUnicode));
	    }
	    interiorRings.add(new LineString(dimension, srid, interior));
    }
    final List<Point> exterior = new ArrayList<Point>();
    for (final String pointCoo : split(first[first.length -1].substring(0, first[first.length -1].length() - 1), ',')) {
      exterior.add(newPoint(null, pointCoo, isNullable, maxLength, precision, scale, isUnicode));
    }

    return new Polygon(dimension, srid, interiorRings, new LineString(dimension, srid, exterior));
  }

  protected Polygon stringToPolygon(final String value, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    final Matcher matcher = getMatcher(PATTERN, value);

    return newPolygon(SRID.valueOf(matcher.group(2)), matcher.group(4),
        isNullable, maxLength, precision, scale, isUnicode);
  }

  protected MultiPolygon stringToMultiPolygon(final String value, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    final Matcher matcher = getMatcher(PATTERN, value);

    final List<Polygon> polygons = new ArrayList<>();
    for (String coo : matcher.group(4).contains(")),((") ?
        matcher.group(4).split("\\)\\),\\(\\(") :
        new String[] { matcher.group(4) }) {

      String polygon = coo;
      if (polygon.startsWith("((")) {
        polygon = polygon.substring(1);
      }
      if (polygon.endsWith("))")) {
        polygon = polygon.substring(0, polygon.length() - 1);
      }
      if (polygon.charAt(0) != '(') {
        polygon = "(" + polygon;
      }
      if (!polygon.endsWith(")")) {
        polygon += ")";
      }

      polygons.add(newPolygon(null, polygon, isNullable, maxLength, precision, scale, isUnicode));
    }

    return new MultiPolygon(dimension, SRID.valueOf(matcher.group(2)), polygons);
  }

  protected GeospatialCollection stringToCollection(final String value, final Boolean isNullable,
      final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode)
          throws EdmPrimitiveTypeException {

    final Matcher matcher = getMatcher(COLLECTION_PATTERN, value);

    Geospatial item = null;
    switch (Geospatial.Type.valueOf(matcher.group(3).toUpperCase())) {
    case POINT:
      item = newPoint(SRID.valueOf(matcher.group(2)), matcher.group(4),
          isNullable, maxLength, precision, scale, isUnicode);
      break;

    case MULTIPOINT:
      final List<Point> points = new ArrayList<>();
      for (final String pointCoo : split(matcher.group(4), ',')) {
        points.add(newPoint(null, pointCoo.substring(1, pointCoo.length() - 1),
            isNullable, maxLength, precision, scale, isUnicode));
      }

      item = new MultiPoint(dimension, SRID.valueOf(matcher.group(2)), points);
      break;

    case LINESTRING:
      item = newLineString(SRID.valueOf(matcher.group(2)), matcher.group(4),
          isNullable, maxLength, precision, scale, isUnicode);
      break;

    case MULTILINESTRING:
      final List<LineString> lineStrings = new ArrayList<>();
      for (final String coo : split(matcher.group(4), ',')) {
        lineStrings.add(newLineString(null, coo.substring(1, coo.length() - 1),
            isNullable, maxLength, precision, scale, isUnicode));
      }

      item = new MultiLineString(this.dimension, SRID.valueOf(matcher.group(2)), lineStrings);
      break;

    case POLYGON:
      item = newPolygon(SRID.valueOf(matcher.group(2)), matcher.group(4),
          isNullable, maxLength, precision, scale, isUnicode);
      break;

    case MULTIPOLYGON:
      final List<Polygon> polygons = new ArrayList<>();
      for (final String coo : split(matcher.group(4), ',')) {
        polygons.add(newPolygon(null, coo.substring(1, coo.length() - 1),
            isNullable, maxLength, precision, scale, isUnicode));
      }

      item = new MultiPolygon(dimension, SRID.valueOf(matcher.group(2)), polygons);
      break;

    default:
    }

    return new GeospatialCollection(dimension, SRID.valueOf(matcher.group(2)),
        Collections.<Geospatial> singletonList(item));
  }

  private StringBuilder toStringBuilder(final SRID srid) {
    return new StringBuilder(dimension.name().toLowerCase()).append('\'').
        append("SRID=").append(srid).append(';');
  }

  private String point(final Point point, final Boolean isNullable,
      final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode)
          throws EdmPrimitiveTypeException {

    return new StringBuilder().
        append(EdmDouble.getInstance().valueToString(point.getX(),
            isNullable, maxLength, precision, scale, isUnicode)).
            append(' ').
            append(EdmDouble.getInstance().valueToString(point.getY(),
                isNullable, maxLength, precision, scale, isUnicode)).
                toString();
  }

  protected String toString(final Point point, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    if (dimension != point.getDimension()) {
      throw new EdmPrimitiveTypeException("The value '" + point + "' is not valid.");
    }

    return toStringBuilder(point.getSrid()).
        append(reference.getSimpleName()).
        append('(').
        append(point(point, isNullable, maxLength, precision, scale, isUnicode)).
        append(")'").
        toString();
  }

  protected String toString(final MultiPoint multiPoint, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    if (dimension != multiPoint.getDimension()) {
      throw new EdmPrimitiveTypeException("The value '" + multiPoint + "' is not valid.");
    }

    final StringBuilder result = toStringBuilder(multiPoint.getSrid()).
        append(reference.getSimpleName()).
        append('(');

    for (final Iterator<Point> itor = multiPoint.iterator(); itor.hasNext();) {
      result.append('(').
      append(point(itor.next(), isNullable, maxLength, precision, scale, isUnicode)).
      append(')');
      if (itor.hasNext()) {
        result.append(',');
      }
    }

    return result.append(")'").toString();
  }

  private StringBuilder appendPoints(final ComposedGeospatial<Point> points, final Boolean isNullable, 
      final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode, 
      final StringBuilder result) throws EdmPrimitiveTypeException {
	for (final Iterator<Point> itor = points.iterator(); itor.hasNext();) {
      result.append(point(itor.next(), isNullable, maxLength, precision, scale, isUnicode));
      if (itor.hasNext()) {
        result.append(',');
      }
    }
	return result;
}

  protected String toString(final LineString lineString, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    if (dimension != lineString.getDimension()) {
      throw new EdmPrimitiveTypeException("The value '" + lineString + "' is not valid.");
    }

    StringBuilder builder = toStringBuilder(lineString.getSrid()).
        append(reference.getSimpleName()).
        append('(');
    return appendPoints(lineString, isNullable, maxLength, precision, scale, isUnicode, builder).
        append(")'").toString();
  }

  protected String toString(final MultiLineString multiLineString, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    if (dimension != multiLineString.getDimension()) {
      throw new EdmPrimitiveTypeException("The value '" + multiLineString + "' is not valid.");
    }

    final StringBuilder result = toStringBuilder(multiLineString.getSrid()).
        append(reference.getSimpleName()).
        append('(');

    for (final Iterator<LineString> itor = multiLineString.iterator(); itor.hasNext();) {
      result.append('(');
      appendPoints(itor.next(), isNullable, maxLength, precision, scale, isUnicode, result).
      append(')');
      if (itor.hasNext()) {
        result.append(',');
      }
    }

    return result.append(")'").toString();
  }

  private String polygon(final Polygon polygon, final Boolean isNullable,
      final Integer maxLength, final Integer precision, final Integer scale, final Boolean isUnicode)
          throws EdmPrimitiveTypeException {

    final StringBuilder result = new StringBuilder();

    for (int i = 0; i < polygon.getNumberOfInteriorRings(); i++) {
	    result.append('(');
	    appendPoints(polygon.getInterior(i), isNullable, maxLength, precision, scale, isUnicode, result);
	    result.append("),");
    }
    
    result.append('(');
    appendPoints(polygon.getExterior(), isNullable, maxLength, precision, scale, isUnicode, result);

    return result.append(')').toString();
  }

  protected String toString(final Polygon polygon, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    if (dimension != polygon.getDimension()) {
      throw new EdmPrimitiveTypeException("The value '" + polygon + "' is not valid.");
    }

    return toStringBuilder(polygon.getSrid()).
        append(reference.getSimpleName()).
        append('(').
        append(polygon(polygon, isNullable, maxLength, precision, scale, isUnicode)).
        append(")'").toString();
  }

  protected String toString(final MultiPolygon multiPolygon, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    if (dimension != multiPolygon.getDimension()) {
      throw new EdmPrimitiveTypeException("The value '" + multiPolygon + "' is not valid.");
    }

    final StringBuilder result = toStringBuilder(multiPolygon.getSrid()).
        append(reference.getSimpleName()).
        append('(');

    for (final Iterator<Polygon> itor = multiPolygon.iterator(); itor.hasNext();) {
      result.append('(').
      append(polygon(itor.next(), isNullable, maxLength, precision, scale, isUnicode)).
      append(')');
      if (itor.hasNext()) {
        result.append(',');
      }
    }

    return result.append(")'").toString();
  }

  protected String toString(final GeospatialCollection collection, final Boolean isNullable, final Integer maxLength,
      final Integer precision, final Integer scale, final Boolean isUnicode) throws EdmPrimitiveTypeException {

    if (dimension != collection.getDimension()) {
      throw new EdmPrimitiveTypeException("The value '" + collection + "' is not valid.");
    }

    StringBuilder result = toStringBuilder(collection.getSrid()).append("Collection(");

    if (collection.iterator().hasNext()) {
      final Geospatial item = collection.iterator().next();
      result.append(item.getClass().getSimpleName()).append('(');

      switch (item.getEdmPrimitiveTypeKind()) {
      case GeographyPoint:
      case GeometryPoint:
        result.append(point((Point) item, isNullable, maxLength, precision, scale, isUnicode));
        break;

      case GeographyMultiPoint:
      case GeometryMultiPoint:
        for (final Iterator<Point> itor = ((MultiPoint) item).iterator(); itor.hasNext();) {
          result.append('(').
          append(point(itor.next(), isNullable, maxLength, precision, scale, isUnicode)).
          append(')');
          if (itor.hasNext()) {
            result.append(',');
          }
        }
        break;

      case GeographyLineString:
      case GeometryLineString:
        appendPoints((LineString) item, isNullable, maxLength, precision, scale, isUnicode, result);
        break;

      case GeographyMultiLineString:
      case GeometryMultiLineString:
        for (final Iterator<LineString> itor = ((MultiLineString) item).iterator(); itor.hasNext();) {
          result.append('(');
          appendPoints(itor.next(), isNullable, maxLength, precision, scale, isUnicode, result).
          append(')');
          if (itor.hasNext()) {
            result.append(',');
          }
        }
        break;

      case GeographyPolygon:
      case GeometryPolygon:
        result.append(polygon((Polygon) item, isNullable, maxLength, precision, scale, isUnicode));
        break;

      case GeographyMultiPolygon:
      case GeometryMultiPolygon:
        for (final Iterator<Polygon> itor = ((MultiPolygon) item).iterator(); itor.hasNext();) {
          result.append('(').
          append(polygon(itor.next(), isNullable, maxLength, precision, scale, isUnicode)).
          append(')');
          if (itor.hasNext()) {
            result.append(',');
          }
        }
        break;

      default:
      }

      result.append(')');
    }

    return result.append(")'").toString();
  }

  private List<String> split(final String input, final char separator) {
    if (input == null) {
      return null;
    }
    List<String> list = new ArrayList<String>();
    int start = 0;
    int end;
    while ((end = input.indexOf(separator, start)) >= 0) {
      list.add(input.substring(start, end));
      start = end + 1;
    }
    if (start < input.length()) {
      list.add(input.substring(start));
    }
    return list;
  }
}
