/***************************************************************************
 * A program illustrating reading miniSEED from buffers
 *
 * This file is part of the miniSEED Library.
 *
 * Copyright (c) 2023 Chad Trabant, EarthScope Data Services
 *
 * 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 <errno.h>
#include <stdio.h>
#include <sys/stat.h>

#include <libmseed.h>
#define TESTCPPDLL_API __declspec(dllexport)

  TESTCPPDLL_API int __stdcall MseedDatas (int argc, char **argv) // MseedDatas(char *argv, int length)
{
  struct stat sb  = {0};
  int64_t records = 0;
  FILE *fh;

  MS3TraceList *mstl    = NULL;
  char *buffer          = NULL;
  uint64_t bufferlength = 0;
  int8_t splitversion   = 0;
  uint32_t flags        = 0;
  int8_t verbose        = 0;

  if (argc != 2)
  {
    ms_log (2, "%s requires a single file name argument\n", argv[0]);
    return -1;
  }

  /* Read specified file into buffer */
  if (!(fh = fopen (argv[1], "rb")))
  {
    ms_log (2, "Error opening %s: %s\n", argv[1], strerror (errno));
    return -1;
  }
  if (fstat (fileno (fh), &sb))
  {
    ms_log (2, "Error stating %s: %s\n", argv[1], strerror (errno));
    return -1;
  }
  if (!(buffer = (char *)malloc (sb.st_size)))
  {
    ms_log (2, "Error allocating buffer of %" PRIsize_t " bytes\n",
            (sb.st_size >= 0) ? (size_t)sb.st_size : 0);
    return -1;
  }
  if (fread (buffer, sb.st_size, 1, fh) != 1)
  {
    ms_log (2, "Error reading file\n");
    return -1;
  }

  fclose (fh);

  bufferlength = sb.st_size;

  /* Set bit flags to validate CRC and unpack data samples */
  flags |= MSF_VALIDATECRC;
  flags |= MSF_UNPACKDATA;

  mstl = mstl3_init (NULL);

  if (!mstl)
  {
    ms_log (2, "Error allocating MS3TraceList\n");
    return -1;
  }

  /* Read all miniSEED in buffer, accumulate in MS3TraceList */
  records = mstl3_readbuffer (&mstl, buffer, bufferlength,
                              splitversion, flags, NULL, verbose);

  if (records < 0)
  {
    ms_log (2, "Problem reading miniSEED from buffer: %s\n", ms_errorstr (records));
  }

  /* Print summary */
  mstl3_printtracelist (mstl, ISOMONTHDAY, 1, 1, 0);

  ms_log (1, "Total records: %" PRId64 "\n", records);

  /* Make sure everything is cleaned up */
  if (mstl)
    mstl3_free (&mstl, 0);

  free (buffer);

  return 0;
}

  typedef struct AsciiDataStruct
  {
    char *sid;
    char *starttime;   //!< Time of first sample
    char *endtime;     //!< Time of last sample
    double samprate;    //!< Nominal sample rate (Hz)
    int64_t samplecnt;  //!< Number of samples in trace coverage
    size_t datasize;    //!< Size of datasamples buffer in bytes
    int64_t numsamples; //!< Number of data samples in datasamples
    char sampletype;    //!< Sample type code, see @ref sample-types
    uint8_t samplesize;
    void *datasamples;  //!< Data samples, \a numsamples of type \a sampletype
  } AsciiDataStruct;
  typedef void (__stdcall *generalDataFunction) (AsciiDataStruct AsciiData);

 generalDataFunction generalData;

  TESTCPPDLL_API void __stdcall MseedDatasCallFun (generalDataFunction fn)
 {
   generalData = fn;
 }
 TESTCPPDLL_API int __stdcall bufferMseedData (int argc, char *argv)
 {
   struct stat sb  = {0};
   int64_t records = 0;
   FILE *fh;

   MS3TraceList *mstl    = NULL;
   char *buffer          = NULL;
   uint64_t bufferlength = 0;
   int8_t splitversion   = 0;
   uint32_t flags        = 0;
   int8_t verbose        = 0;

   // if (argc != 2)
   //{
   //   ms_log (2, "%s requires a single file name argument\n", argv[0]);
   //   return -1;
   // }

   /* Read specified file into buffer
   if (!(fh = fopen (argv[1], "rb")))
   {
     ms_log (2, "Error opening %s: %s\n", argv[1], strerror (errno));
     return -1;
   }
   if (fstat (fileno (fh), &sb))
   {
     ms_log (2, "Error stating %s: %s\n", argv[1], strerror (errno));
     return -1;
   }
   if (!(buffer = (char *)malloc (sb.st_size)))
   {
     ms_log (2, "Error allocating buffer of %" PRIsize_t " bytes\n",
             (sb.st_size >= 0) ? (size_t)sb.st_size : 0);
     return -1;
   }
   if (fread (buffer, sb.st_size, 1, fh) != 1)
   {
     ms_log (2, "Error reading file\n");
     return -1;
   }

   fclose (fh);
   */
   bufferlength = argc;
   // buffer       = argv;
   /* Set bit flags to validate CRC and unpack data samples */
   flags |= MSF_VALIDATECRC;
   flags |= MSF_UNPACKDATA;

   mstl = mstl3_init (NULL);

   if (!mstl)
   {
     ms_log (2, "Error allocating MS3TraceList\n");
     return -1;
   }

   /* Read all miniSEED in buffer, accumulate in MS3TraceList */
   records = mstl3_readbuffer (&mstl, argv, bufferlength,
                               splitversion, flags, NULL, verbose);

   if (records < 0)
   {
     ms_log (2, "Problem reading miniSEED from buffer: %s\n", ms_errorstr (records));
   }

   /* Print summary */
   // mstl3_printtracelist (mstl, ISOMONTHDAY, 1, 1, 0);

   /* Traverse trace list structures and print summary information */
   MS3TraceID *tid = mstl->traces.next[0];
   char starttimestr[30];
   char endtimestr[30];
   MS3TraceSeg *seg     = NULL;
   MS3RecordPtr *recptr = NULL;

   char *mseedfile = NULL;
   char bufferptrstr[30];
   char fileptrstr[30];
   size_t idx;
   int rv;

   char printdata = 'd';
   int64_t unpacked;
   uint8_t samplesize;
   char sampletype;
   size_t lineidx;
   size_t lines;
   int col;
   void *sptr;
   AsciiDataStruct ybbmqj;
   /* Traverse trace list structures and print summary information */
   tid = mstl->traces.next[0];
   while (tid)
   {
     ms_log (0, "TraceID for %s (%d), segments: %u\n",
             tid->sid, tid->pubversion, tid->numsegments);

     seg = tid->first;
     while (seg)
     {
       if (!ms_nstime2timestr (seg->starttime, starttimestr, ISOMONTHDAY, NANO) ||
           !ms_nstime2timestr (seg->endtime, endtimestr, ISOMONTHDAY, NANO))
       {
         ms_log (2, "Cannot create time strings\n");
         starttimestr[0] = endtimestr[0] = '\0';
       }

       ms_log (0, "  Segment %s - %s, samples: %" PRId64 ", sample rate: %g\n",
               starttimestr, endtimestr, seg->samplecnt, seg->samprate);

       unpacked   = seg->numsamples; // mstl3_unpack_recordlist (tid, seg, NULL, 0, verbose);
       sampletype = seg->sampletype;
       samplesize = ms_samplesize (seg->sampletype);

       if (unpacked != seg->samplecnt)
       {
         ms_log (2, "Cannot unpack samples for %s\n", tid->sid);
       }
       else
       {
         ms_log (0, "DATA (%" PRId64 " samples) of type '%c':\n", seg->numsamples, seg->sampletype);

         if (sampletype == 't')
         {
           printf ("%*s",
                   (seg->numsamples > INT_MAX) ? INT_MAX : (int)seg->numsamples,
                   (char *)seg->datasamples);
         }
         else
         {
           ybbmqj.sid         = tid->sid;
           ybbmqj.starttime   = starttimestr;
           ybbmqj.endtime     = endtimestr;
           ybbmqj.samprate    = seg->samprate;
           ybbmqj.samplecnt   = seg->samplecnt;
           ybbmqj.datasamples = seg->datasamples;
           ybbmqj.numsamples  = seg->numsamples;
           ybbmqj.datasize    = seg->datasize;
           ybbmqj.samplesize  = samplesize;
           ybbmqj.sampletype  = seg->sampletype;
           if (generalData != NULL)
           {
             generalData (ybbmqj);
           }
           lines = (unpacked / 6) + 1;
           //for (idx = 0, lineidx = 0; lineidx < lines; lineidx++)
           //{
           //  for (col = 0; col < 6 && idx < seg->numsamples; col++)
           //  {
           //    sptr = (char *)seg->datasamples + (idx * samplesize);

           //    if (sampletype == 'i')
           //      ms_log (0, "%10d  ", *(int32_t *)sptr);

           //    else if (sampletype == 'f')
           //      ms_log (0, "%10.8g  ", *(float *)sptr);

           //    else if (sampletype == 'd')
           //      ms_log (0, "%10.10g  ", *(double *)sptr);

           //    idx++;
           //  }
           //  ms_log (0, "\n");

           //  //   if (printdata == 'd')
           //  //    break;
           //}
         }
         seg = seg->next;
       }
     }
    tid = tid->next[0];
   }
   //****************************************************

   ms_log (1, "Total records: %" PRId64 "\n", records);

   /* Make sure everything is cleaned up */
   if (mstl)
     mstl3_free (&mstl, 0);

   free (buffer);

   return 0;
 }




