// 
// ======================================================================
// Copyright (C) 2000-2003 Instrumental Software Technologies, Inc. (ISTI)
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. If modifications are performed to this code, please enter your own 
// copyright, name and organization after that of ISTI.
// 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. All advertising materials mentioning features or use of this
// software must display the following acknowledgment:
// "This product includes software developed by Instrumental
// Software Technologies, Inc. (http://www.isti.com)"
// 4. If the software is provided with, or as part of a commercial
// product, or is used in other commercial software products the
// customer must be informed that "This product includes software
// developed by Instrumental Software Technologies, Inc.
// (http://www.isti.com)"
// 5. The names "Instrumental Software Technologies, Inc." and "ISTI"
// must not be used to endorse or promote products derived from
// this software without prior written permission. For written
// permission, please contact "info@isti.com".
// 6. Products derived from this software may not be called "ISTI"
// nor may "ISTI" appear in their names without prior written
// permission of Instrumental Software Technologies, Inc.
// 7. Redistributions of any form whatsoever must retain the following
// acknowledgment:
// "This product includes software developed by Instrumental
// Software Technologies, Inc. (http://www.isti.com/)."
// 8. Redistributions of source code, or portions of this source code,
// must retain the above copyright notice, this list of conditions
// and the following disclaimer.
// THIS SOFTWARE IS PROVIDED BY INSTRUMENTAL SOFTWARE
// TECHNOLOGIES, INC. "AS IS" AND ANY EXPRESSED 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 INSTRUMENTAL SOFTWARE TECHNOLOGIES,
// INC. OR ITS 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 <stdio.h>
#include <string.h>
#include "die.h"
#include "main.h"
#include "config.h"
#include "global.h"
#include "externs.h"
#include "scn_map.h"
extern "C" {
#  include "kom.h"
#  include "earthworm.h"
};

ConfigType gConfig;
unsigned char TypeTrace;         /* Trace EW type for logo */
unsigned char TypeHB;            /* HB=HeartBeat EW type for logo */
unsigned char TypeErr;           /* Error EW type for logo */
unsigned char QModuleId;
/*
 * Does this line contain useful information 
 * (is it worth parsing)
 */
int isUsefulLine(char *line) {
    char *pos;
    /* take care of the simple cases */
    if( !strlen(line) || line[0] == '\n' || line[0] == '#' ) {
        return FALSE;
    }
    pos = line;
    while(pos) {
        if(*pos == '#' || *pos == '\0') {
            return FALSE;
        }

        if(*pos != ' ' && *pos != '\t') { 
            return TRUE;
        }
        pos++;
    }
   return FALSE;
}


/*
 * Read the config file and populate the gConfig structure
 */
int readConfig(char *configFile) {
    if(!k_open(configFile)) {
      fprintf(stderr, "Unable to open config file: %s\n", configFile);
      return -1;
    }

    /*
     * read each line
     */
    while(k_rd()) {
        char *thisLine = k_get();
        char *token;

        /* ignore comment/blank lines */
        if(!isUsefulLine(thisLine)) {
            continue;
        }

        token = k_str();

#ifdef _DEBUG
		fprintf(stderr, "TOKEN: %s\n", token);

#endif

        /*
	 * check for the various config items
	 */

        if(k_its("ModuleId")) {
            token = k_str();
            memcpy(gConfig.ModuleId, token, strlen(token)+1);
			if(GetModId(token, &QModuleId) == -1) {
                  fprintf( stderr, "%s: Invalid ModuleId <%s>. \n", Q3302EW_NAME, token );
                  fprintf( stderr, "%s: Please Register ModuleId <%s> in earthworm.d!\n", Q3302EW_NAME, token );
                  return -1;
			}
        } else if(k_its("RingName")) {
            token = k_str();
            memcpy(gConfig.RingName, token, strlen(token)+1);
	    gConfig.RingKey = GetKey(token);
        } else if(k_its("HeartbeatInt")) {
            gConfig.HeartbeatInt = k_int();
        } else if(k_its("LogFile")) {
            gConfig.LogFile = k_int();
        } else if(k_its("udpaddr")) {
      	    token = k_str();
	    memcpy(gConfig.udpaddr, token, strlen(token) + 1);
	} else if(k_its("ipport")) {
	    gConfig.ipport = k_int();
	} else if(k_its("baseport")) {
	    gConfig.baseport = k_int();	  
	} else if(k_its("dataport")) {
	    gConfig.dataport = k_int();
	} else if(k_its("serialnumber")) {
	    token = k_str();
	    memcpy(gConfig.serialnumber, token, strlen(token) + 1);
	} else if(k_its("authcode")) {
	    token = k_str();
	    memcpy(gConfig.authcode, token, strlen(token) + 1);
	} else if(k_its("verbosity")) {
	  gConfig.verbosity = k_int();
	} else if(k_its("startmsg")) {
	  token = k_str();
	  memcpy(gConfig.startmsg, token, strlen(token) + 1);
	} else if(k_its("statusinterval")) {
	  gConfig.statusinterval = k_int();
	} else if(k_its("MinClockQuality")) {
	  gConfig.minclockquality = k_int();
	} else if(k_its("diagnostic")) {
	  gConfig.diagnostic = k_int();
	} else if(k_its("MaxMass1Position")) {
	  gConfig.maxmass1position = k_int();
	} else if(k_its("MinMass1Position")) {
	  gConfig.minmass1position = k_int();
	} else if(k_its("MaxMass2Position")) {
	  gConfig.maxmass2position = k_int();
	} else if(k_its("MinMass2Position")) {
	  gConfig.minmass2position = k_int();
	} else if(k_its("MaxMass3Position")) {
	  gConfig.maxmass3position = k_int();
	} else if(k_its("MinMass3Position")) {
	  gConfig.minmass3position = k_int();
	} else if(k_its("MaxMass4Position")) {
	  gConfig.maxmass4position = k_int();
	} else if(k_its("MinMass4Position")) {
	  gConfig.minmass4position = k_int();
	} else if(k_its("MaxMass5Position")) {
	  gConfig.maxmass5position = k_int();
	} else if(k_its("MinMass5Position")) {
	  gConfig.minmass5position = k_int();
	} else if(k_its("MaxMass6Position")) {
	  gConfig.maxmass6position = k_int();
	} else if(k_its("MinMass6Position")) {
	  gConfig.minmass6position = k_int();
	} else if(k_its("MinInputPower")) {
	  gConfig.mininputpower = k_int();
	} else if(k_its("MaxInputPower")) {
	  gConfig.maxinputpower = k_int();
	} else if ( k_its( "SCN2pinmap") ) {
            char *S,*C,*N;
            int pin;
            S=k_str();
            C=k_str();
            N=k_str();
            pin=k_int();
            if (insertSCN(S,C,N,pin) == -1) {
                  fprintf( stderr, "%s: Invalid SCN2pinmap entry <%s %s %s %d>.\n", Q3302EW_NAME, S,C,N,pin);
                  fprintf( stderr, "Follow the SEED header definitions!\n");
            }
	} else {
            fprintf(stderr, "%s: Unknown config command (%d)\n", Q3302EW_NAME, strlen(thisLine));
        }
    }

    /*
     * this is a good time to populate the ConfigVO for mountianair code
     */
    g_cvo.setQ330UdpAddr(gConfig.udpaddr);
    g_cvo.setQ330BasePort(gConfig.baseport);
    g_cvo.setQ330DataPortNumber(gConfig.dataport);
    g_cvo.setQ330SerialNumber(gConfig.serialnumber);
    g_cvo.setQ330AuthCode(gConfig.authcode);
    g_cvo.setQMAIPPort(gConfig.ipport);
    g_cvo.setVerbosity(gConfig.verbosity);
    g_cvo.setDiagnostic((qma_uint32) gConfig.diagnostic);
    g_cvo.setStartMsg(gConfig.startmsg);
    g_cvo.setStatusInterval(gConfig.statusinterval);
    //g_cvo.setDataRateInterval(gConfig.datarateinterval);
    return 1;
}
  
void printConfigStructToStdErr() {

    fprintf(stderr, "*** %s Config\n", Q3302EW_NAME);
    fprintf(stderr, "    ModuleId:        %s\n", gConfig.ModuleId);
    fprintf(stderr, "    RingName:        %s\n", gConfig.RingName); 
    fprintf(stderr, "    RingKey:         %8d\n", gConfig.RingKey); 
    fprintf(stderr, "    HeartbeatInt:    %d\n", gConfig.HeartbeatInt); 
    fprintf(stderr, "    LogFile:         %d\n", gConfig.LogFile); 
    fprintf(stderr, "    udpaddr:         %s\n", gConfig.udpaddr); 
    fprintf(stderr, "    ipport:          %d\n", gConfig.ipport); 
    fprintf(stderr, "    baseport:        %d\n", gConfig.baseport); 
    fprintf(stderr, "    dataport:        %d\n", gConfig.dataport); 
    fprintf(stderr, "    seralnumber:     %s\n", gConfig.serialnumber); 
    fprintf(stderr, "    authcode:        %s\n", gConfig.authcode); 
    fprintf(stderr, "    verbosity:       %d\n", gConfig.verbosity); 
    fprintf(stderr, "    startmsg:        %s\n", gConfig.startmsg); 
    fprintf(stderr, "    statusinterval:  %d\n", gConfig.statusinterval); 
    fprintf(stderr, "    minclockquality: %d\n", gConfig.minclockquality); 
    fprintf(stderr, "    diagnostic:      %d\n", gConfig.diagnostic); 
}
    
    


