// Copyright (c) 2012 by Zuse-Institute Berlin and the Technical University of Denmark.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//     1. Redistributions of source code must retain the above copyright
//        notice, this list of conditions and the following disclaimer.
//     2. Redistributions in binary form must reproduce the above copyright
//        notice, this list of conditions and the following disclaimer in the
//        documentation and/or other materials provided with the distribution.
//     3. Neither the name of the copyright holders nor contributors may not
//        be used to endorse or promote products derived from this software
//        without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS NOR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "sysconverter.h"

#include <string.h>
#include <stdlib.h>
#include <stdio.h>

static CBFresponsee swapfiledirandext(
    const char * ifile,
    const char * newpath,
    const char * newformat,
    char * ofile);

static CBFresponsee processfile(
    const CBFfrontend *frontend,
    const CBFbackend *backend,
    const char *ifile,
    const char *iformat,
    const char *ofile,
    const char *oformat);


// -------------------------------------
// Function definitions
// -------------------------------------

CBFresponsee CBF_convertfiles(int argc, char *argv[],
    const CBFfrontend *frontend,
    const CBFbackend *backend,
    const char *iformat,
    const char *oformat,
    const char *opath)
{
  CBFresponsee res = CBF_RES_OK;
  char *ifile = NULL;
  char *ofile = NULL;
  int i, maxlen;

  // Forall non-nullified arguments
  for (i=1; i<argc && res==CBF_RES_OK; ++i) {
    if (argv[i]) {
      ifile = argv[i];

      // Determine output filename
      if ( res==CBF_RES_OK ) {
        if (opath != NULL)
          maxlen = strlen(opath) + 1;
        else
          maxlen = 0;

        maxlen += strlen(ifile) + 1 + strlen(oformat) + 1;
        ofile = (char*) calloc(maxlen, sizeof(char));
        if (!ofile) {
          res = CBF_RES_ERR;
          break;
        }

        res = swapfiledirandext(ifile, opath, oformat, ofile);
      }

      if ( res==CBF_RES_OK )
        res = processfile(frontend, backend, ifile, iformat, ofile, oformat);

      free(ofile);
    }
  }
  return res;
}

static CBFresponsee swapfiledirandext(
    const char * ifile,
    const char * newpath,
    const char * newformat,
    char * ofile)
{
  CBFresponsee res = CBF_RES_OK;
  int i=0, j=0, k;

  if ( ofile ) {
    if ( newpath && newpath[0]!='\0' ) {
      // Write newpath and make sure it ends with a path separator
      strcpy(ofile, newpath);
      while(ofile[i]!='\0') ++i;
      if (ofile[i-1]!='/' && ofile[i-1]!='\\') {
        strcpy(ofile+i, "/");
        ++i;
      }

      // Skip forward to ifile basename
      k = 0;
      while(ifile[k]!='\0') {
        if (ifile[k]=='/' || ifile[k]=='\\') j = k+1;
        ++k;
      }
    }

    // Write relevant part of ifile
    strcpy(ofile+i, ifile+j);

    // Skip forward to ofile basename and change format
    k = i;
    while(ofile[k]!='\0') {
      if (ifile[k]=='/' || ifile[k]=='\\') i = k+1;
      ++k;
    }
    while(ofile[i]!='\0' && ofile[i]!='.') ++i;
    strcpy(ofile+i, ".");
    strcpy(ofile+i+1, newformat);
  }
  else {
    res = CBF_RES_ERR;
  }

  return res;
}

static CBFresponsee processfile(
    const CBFfrontend *frontend,
    const CBFbackend *backend,
    const char *ifile,
    const char *iformat,
    const char *ofile,
    const char *oformat)
{
  CBFresponsee res = CBF_RES_OK;
  CBFfrontendmemory mem = {0};
  CBFdata data = {0};

  // Read file
  res = frontend->read(ifile, iformat, &data, &mem);

  if ( res!=CBF_RES_OK )
    printf("Failed to read file: %s\n", ifile);
  else
  {
    // Write file
    res = backend->write(ofile, oformat, data);

    if ( res!=CBF_RES_OK )
      printf("Failed to write file: %s\n", ofile);

    // Clean data structure
    frontend->clean(&data, &mem);
  }

  return res;
}
