/*
 * Copyright 2013 georgeathanasopoulos.
 *
 * 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.
 */

package eu.dnetlib.espas.util.sat;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.sql.Timestamp;
import java.util.LinkedList;
import java.util.List;
import org.apache.log4j.Logger;

/**
 * SatLocationParser is used for parsing the satellite location file content, which is formated similar to the format used in 
 * {@link http://www.espas-fp7.eu/trac/attachment/wiki/guidelines/InstructionsDataProviders2/location.txt}.
 * 
 * @author george.athanasopoulos
 */

public class SatLocationParser {
    Logger _logger = Logger.getLogger(SatLocationParser.class);
    
    public LinkedList<Point4D> satPoints;
    
    public SatLocationParser(){
        satPoints = new LinkedList<Point4D>();
    }

    public void parse(InputStream contentStream) throws IOException{
        _logger.debug("Processing satelite location information stream");
//        create tokenizer;
        StreamTokenizer strTokenizer = createTokenizer(contentStream);
//      process file raws
     boolean flag_CONTINUE = true;   
     String timeValue=null;
     double x=Double.NaN, y=Double.NaN, z=Double.NaN;
     String crsName="";
     
     do{
         
         int tt = strTokenizer.nextToken();
         _logger.info("Token value is:"+strTokenizer.toString());
         switch(tt){
             
//                 this is the end of the file
             case StreamTokenizer.TT_EOF: 
                 flag_CONTINUE=false; 
                 break;
                 
//                  this is the end of a row; clean vars and call readLine
             case StreamTokenizer.TT_EOL: 
//                 add this point only if there is a timestamp element specified and at least one of the coordinates
                 if(timeValue!=null && (x!=Double.NaN || y!=Double.NaN || z!=Double.NaN))
                    satPoints.add(readLine(timeValue,x,y,z,crsName));
                 timeValue = null;x=Double.NaN; y=Double.NaN; z=Double.NaN;
                 break;
                 
//                 this could be any of the 3 dimensional axis values in accordance to the x,y,z order
             case StreamTokenizer.TT_NUMBER: 
                 if(x!= Double.NaN)
                     x=strTokenizer.nval;
                 else if(y!= Double.NaN)
                     y=strTokenizer.nval;
                 else if(z!= Double.NaN)
                     z=strTokenizer.nval;
                 break;
                 
//                 normally this means that we have a timestamp description
             case StreamTokenizer.TT_WORD:
                 if(strTokenizer.sval.contains("crs="))
                    crsName=strTokenizer.sval.replaceFirst(".*crs=", "").trim(); 
                 else
                    timeValue = strTokenizer.sval;
                 break;
                 
             default:
                 _logger.error("Discovered error in tokens while processing satelite location information stream. While have to stop location harvesting process. Error in line : "+strTokenizer.lineno());
                 flag_CONTINUE=false;
                 break;
         }

     }while(flag_CONTINUE);        
     
     _logger.debug("Location stream parsing finished. Harvested points are :"+satPoints.size());
    }
    
    public List<Point4D> getSatPoints(){
        return satPoints;
    }
    
    private Point4D readLine(String time, double x, double y, double z, String crsName){
        Point4D point = new Point4D(Timestamp.valueOf(time),x,y,z, crsName);
        return point;
    }
    
    private StreamTokenizer createTokenizer(InputStream contentStream) {
        InputStreamReader inReader = new InputStreamReader(contentStream);
        StreamTokenizer strTokenizer = new StreamTokenizer(inReader);
        strTokenizer.commentChar('#');
        strTokenizer.wordChars('%', '%');
        strTokenizer.wordChars(':', ':');
        strTokenizer.wordChars('=', '=');
        strTokenizer.wordChars('/', '/');
        strTokenizer.wordChars('-', '-');
        strTokenizer.wordChars('?', '?');
        strTokenizer.eolIsSignificant(true);
        return strTokenizer;
    }

}
