/*
 * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed 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.
 */


#include <cstdlib>
#include <fstream>
#include <sstream>

#include "otb_ossim.h"

#if defined(__GNUC__) || defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Woverloaded-virtual"
#pragma GCC diagnostic ignored "-Wshadow"
#include "ossim/elevation/ossimElevManager.h"
#include "ossim/base/ossimFilename.h"
#pragma GCC diagnostic pop
#else
#include "ossim/elevation/ossimElevManager.h"
#include "ossim/base/ossimFilename.h"
#endif

int otbOssimElevManagerTest4(int argc, char* argv[])
{

  if (argc != 9)
  {
    std::cout << "Usage: " << std::endl;
    std::cout << argv[0] << " srtmDir outfname originX originY spacingX spacingY sizeX sizeY" << std::endl;
    return EXIT_FAILURE;
  }

  const ossimFilename srtmDir(argv[1]);
  const char*         outfname = argv[2];

  double origin[2];
  double spacing[2];
  int    size[2];

  origin[0]  = atof(argv[3]);
  origin[1]  = atof(argv[4]);
  spacing[0] = atof(argv[5]);
  spacing[1] = atof(argv[6]);
  size[0]    = atoi(argv[7]);
  size[1]    = atoi(argv[8]);

  double* image = new double[size[0] * size[1]];

  ossimElevManager* elevManager = ossimElevManager::instance();

  elevManager->loadElevationPath(srtmDir);

  for (int j = 0; j < size[1]; ++j)
  {
    for (int i = 0; i < size[0]; ++i)
    {
      double point[2];
      point[0] = origin[0] + i * spacing[0];
      point[1] = origin[1] + j * spacing[1];

      ossimGpt ossimWorldPoint;
      ossimWorldPoint.lon = point[0];
      ossimWorldPoint.lat = point[1];
      double height       = elevManager->getHeightAboveMSL(ossimWorldPoint);

      if (!ossim::isnan(height))
      {
        // Fill the image
        image[i + j * size[0]] = height;
      }
      else
      {
        // Back to the MNT default value
        image[i + j * size[0]] = 0;
      }
    }
  }

  std::ofstream file;
  std::cout << outfname << std::endl;
  file.open(outfname, std::ios::binary | std::ios::out);

  file.write(reinterpret_cast<char*>(image), sizeof(double) * size[0] * size[1]);
  file.close();

  delete[] image;

  // Create the header
  std::stringstream headerName;
  headerName << outfname << ".hdr";
  std::ofstream headerFile;
  headerFile.open(headerName.str());
  headerFile << "ENVI" << std::endl;
  headerFile << "samples = " << size[0] << std::endl;
  headerFile << "lines   = " << size[1] << std::endl;
  headerFile << "bands   = 1" << std::endl;
  headerFile << "header offset = 0" << std::endl;
  headerFile << "file type = ENVI Standard" << std::endl;
  headerFile << "data type = 5" << std::endl;
  headerFile << "interleave = bsq" << std::endl;
  headerFile << "byte order = 0" << std::endl;
  headerFile << std::endl;
  headerFile.close();

  // Check for the index 216, 51 (difference of 4 in the output)
  {
    int    i = 216;
    int    j = 51;
    double point[2];
    point[0] = origin[0] + i * spacing[0];
    point[1] = origin[1] + j * spacing[1];

    ossimGpt ossimWorldPoint;
    ossimWorldPoint.lon = point[0];
    ossimWorldPoint.lat = point[1];
    double height       = elevManager->getHeightAboveMSL(ossimWorldPoint);
    std::cout << "Output value at (216, 51): " << height << std::endl;
    std::cout << "At lon: " << ossimWorldPoint.lon << " , lat: " << ossimWorldPoint.lat << std::endl;
  }

  return EXIT_SUCCESS;
}
