/******************************************************************************
 * $Id$
 *
 * Project:  MapServer
 * Purpose:  Headers for mapkml.cpp Google Earth KML output
 * Author:   David Kana and the MapServer team
 *
 ******************************************************************************
 * Copyright (c) 1996-2009 Regents of the University of Minnesota.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies of this Software or works derived from this Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *****************************************************************************/
#include "mapserver.h"

#ifdef USE_KML

#include "mapkmlrenderer.h"

#ifdef __cplusplus
extern "C" {
#endif

KmlRenderer *getKmlRenderer(imageObj *img) {
  return (KmlRenderer *)img->img.plugin;
}

imageObj *msCreateImageKml(int width, int height, outputFormatObj *format,
                           colorObj *bg) {
  imageObj *image = NULL;

  image = (imageObj *)malloc(sizeof(imageObj));
  MS_CHECK_ALLOC(image, sizeof(imageObj), NULL);
  memset(image, 0, sizeof(imageObj));

  KmlRenderer *ren = new KmlRenderer(width, height, format, bg);
  image->img.plugin = (void *)ren;

  return image;
}

int msSaveImageKml(imageObj *img, mapObj * /*map*/, FILE *fp,
                   outputFormatObj *format) {
  KmlRenderer *renderer = getKmlRenderer(img);
  return renderer->saveImage(img, fp, format);
}

int msRenderLineKml(imageObj *img, shapeObj *p, strokeStyleObj *style) {
  KmlRenderer *renderer = getKmlRenderer(img);
  renderer->renderLine(img, p, style);
  return MS_SUCCESS;
}

int msRenderPolygonKml(imageObj *img, shapeObj *p, colorObj *color) {
  KmlRenderer *renderer = getKmlRenderer(img);
  renderer->renderPolygon(img, p, color);
  return MS_SUCCESS;
}

int msRenderPolygonTiledKml(imageObj * /*img*/, shapeObj * /*p*/,
                            imageObj * /*tile*/) {
  /*KmlRenderer* renderer = getKmlRenderer(img);*/
  return MS_SUCCESS;
}

int msRenderLineTiledKml(imageObj * /*img*/, shapeObj * /*p*/,
                         imageObj * /*tile*/) {
  return MS_SUCCESS;
}

int msRenderGlyphsKml(imageObj *img, const textSymbolObj *ts, colorObj *c,
                      colorObj *oc, int ow, int /*isMarker*/) {
  KmlRenderer *renderer = getKmlRenderer(img);
  renderer->renderGlyphs(img, ts, c, oc, ow);
  return MS_SUCCESS;
}

int msRenderVectorSymbolKml(imageObj *img, double x, double y,
                            symbolObj *symbol, symbolStyleObj *style) {
  KmlRenderer *renderer = getKmlRenderer(img);
  renderer->renderVectorSymbol(img, x, y, symbol, style);
  return MS_SUCCESS;
}

int msRenderPixmapSymbolKml(imageObj *img, double x, double y,
                            symbolObj *symbol, symbolStyleObj *style) {
  KmlRenderer *renderer = getKmlRenderer(img);
  renderer->renderPixmapSymbol(img, x, y, symbol, style);
  return MS_SUCCESS;
}

int msRenderEllipseSymbolKml(imageObj *image, double x, double y,
                             symbolObj *symbol, symbolStyleObj *style) {
  KmlRenderer *renderer = getKmlRenderer(image);
  renderer->renderEllipseSymbol(image, x, y, symbol, style);
  return MS_SUCCESS;
}

int msRenderTruetypeSymbolKml(imageObj *image, double x, double y,
                              symbolObj *symbol, symbolStyleObj *style) {
  KmlRenderer *renderer = getKmlRenderer(image);
  renderer->renderTruetypeSymbol(image, x, y, symbol, style);
  return MS_SUCCESS;
}

int msRenderTileKml(imageObj * /*img*/, imageObj * /*tile*/, double /*x*/,
                    double /*y*/) {
  return MS_SUCCESS;
}

int msGetRasterBufferKml(imageObj * /*img*/, rasterBufferObj * /*rb*/) {
  return MS_FAILURE; // not supported for kml
}

int msGetTruetypeTextBBoxKml(rendererVTableObj * /*r*/, char ** /*fonts*/,
                             int /*numfonts*/, double size, char *string,
                             rectObj *rect, double **advances,
                             int /*bAdjustBaseline*/) {
  rect->minx = 0.0;
  rect->maxx = 0.0;
  rect->miny = 0.0;
  rect->maxy = 0.0;
  if (advances) {
    int numglyphs = msGetNumGlyphs(string);
    *advances = (double *)msSmallMalloc(numglyphs * sizeof(double));
    for (int i = 0; i < numglyphs; i++) {
      (*advances)[i] = size;
    }
  }
  return MS_SUCCESS;
}

int msStartNewLayerKml(imageObj *img, mapObj * /*map*/, layerObj *layer) {
  KmlRenderer *renderer = getKmlRenderer(img);
  return renderer->startNewLayer(img, layer);
}

int msCloseNewLayerKml(imageObj *img, mapObj * /*map*/, layerObj *layer) {
  KmlRenderer *renderer = getKmlRenderer(img);
  return renderer->closeNewLayer(img, layer);
}

int msFreeImageKml(imageObj *image) {
  KmlRenderer *renderer = getKmlRenderer(image);
  if (renderer) {
    delete renderer;
  }
  image->img.plugin = NULL;
  return MS_SUCCESS;
}

int msFreeSymbolKml(symbolObj * /*symbol*/) { return MS_SUCCESS; }

int msStartShapeKml(imageObj *img, shapeObj *shape) {
  KmlRenderer *renderer = getKmlRenderer(img);
  renderer->startShape(img, shape);
  return MS_SUCCESS;
}

int msEndShapeKml(imageObj *img, shapeObj *shape) {
  KmlRenderer *renderer = getKmlRenderer(img);
  renderer->endShape(img, shape);
  return MS_SUCCESS;
}

int msMergeRasterBufferKml(imageObj *dest, rasterBufferObj *overlay,
                           double /*opacity*/, int /*srcX*/, int /*srcY*/,
                           int /*dstX*/, int /*dstY*/, int /*width*/,
                           int /*height*/) {
  KmlRenderer *renderer = getKmlRenderer(dest);
  return renderer->mergeRasterBuffer(dest, overlay);
}

#ifdef __cplusplus
}
#endif

#endif /*USE_KML*/

int aggInitializeRasterBuffer(rasterBufferObj *rb, int width, int height,
                              int mode);

int msPopulateRendererVTableKML(rendererVTableObj *renderer) {
#ifdef USE_KML
  renderer->supports_pixel_buffer = 0;
  renderer->supports_clipping = 0;
  renderer->use_imagecache = 0;
  renderer->default_transform_mode = MS_TRANSFORM_NONE;

  renderer->startLayer = msStartNewLayerKml;
  renderer->endLayer = msCloseNewLayerKml;
  renderer->renderLine = &msRenderLineKml;
  renderer->createImage = &msCreateImageKml;
  renderer->saveImage = &msSaveImageKml;
  renderer->renderPolygon = &msRenderPolygonKml;
  renderer->renderGlyphs = &msRenderGlyphsKml;
  renderer->renderEllipseSymbol = &msRenderEllipseSymbolKml;
  renderer->renderVectorSymbol = &msRenderVectorSymbolKml;
  renderer->renderPixmapSymbol = &msRenderPixmapSymbolKml;
  renderer->mergeRasterBuffer = &msMergeRasterBufferKml;
  renderer->loadImageFromFile = msLoadMSRasterBufferFromFile;
  renderer->initializeRasterBuffer = aggInitializeRasterBuffer;
  renderer->renderTile = &msRenderTileKml;
  renderer->renderPolygonTiled = &msRenderPolygonTiledKml;
  renderer->renderLineTiled = NULL;
  renderer->freeSymbol = &msFreeSymbolKml;
  renderer->freeImage = &msFreeImageKml;
  renderer->mergeRasterBuffer = msMergeRasterBufferKml;
  renderer->compositeRasterBuffer = NULL;

  renderer->startShape = &msStartShapeKml;
  renderer->endShape = &msEndShapeKml;

  return MS_SUCCESS;
#else
  (void)renderer;
  msSetError(MS_MISCERR, "KML Driver requested but is not built in",
             "msPopulateRendererVTableKML()");
  return MS_FAILURE;
#endif
}
