/*
 * Copyright 2015 Andrew T. Flowers, K0SM
 * 
 * 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 dopplerpsk;

import dopplerpsk.util.Sqf;
import dopplerpsk.util.SqfParser;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * The class loads and provides satellite information (orbital elements and
 * frequency information).  It is essentially a wrapper class for the TLE files 
 * and doppler.sqf.
 * 
 * @author Andrew T. Flowers
 */
public class SatelliteDirectory {

    private final TreeMap<String, Satellite> satelliteMap;
    private final File tleDirectory;
    private final SqfParser sqfParser;

    /**
     * Creates a new satellite directory using the suppled TLE directory
     * and sqf file.
     * 
     * The satellites should be read into memory by calling loadSatellites().
     * 
     * @param tleDirectory
     * @param sqf 
     */
    public SatelliteDirectory(File tleDirectory, File sqf) {
        satelliteMap = new TreeMap();
        this.tleDirectory = tleDirectory;
        sqfParser = new SqfParser(sqf);
    }

    /**
     * Gets a list of satellites that have been loaded into the directory.  This
     * is useful for providing a list of satellites from which to choose.  The
     * names are in lexical order.  The names are taken from the TLE headers
     * for each set of TLEs.
     * 
     * @return available satellites in lexical order
     */
    public String[] getSatelliteNames() {
        Set<String> names = satelliteMap.keySet();
        String[] arr = new String[names.size()];
        int i = 0;
        for (String n : names) {
            arr[i] = n;
            i++;
        }
        return arr;
    }

    /**
     * Loads the satellite information from the TLE directory and SQF file. If 
     * no doppler.sqf frequency information is specified for the satellite, it 
     * will assume frequencies of 0 Hz.
     * 
     * @throws FileNotFoundException 
     */
    public void loadSatellites() throws FileNotFoundException {

        loadSqf();
        File[] tleFiles = tleDirectory.listFiles();
        String name = null;
        String line1 = null;
        String line2 = null;
        for (File f : tleFiles) {

            BufferedReader br = null;
            try {
                br = new BufferedReader(new FileReader(f));
                String line = br.readLine();
                while (line != null) {
                    line = line.trim();
                    if (line.startsWith("1 ")) {

                        // Hack for AMSAT keps--it has an example TLE schema
                        // in the file header that we need to igore.
                        if (name != null && !name.contains("DECODE 2-LINE")) {
                            line1 = line;
                        }
                    } else if (line.startsWith("2 ")) {
                        if (name != null && line1 != null) {
                            line2 = line;

                            
                            double downlinkFreq = 0;
                                double uplinkFreq = 0;
                             
                                boolean inverting = false;
                                
                            Sqf sqf = sqfParser.getSqf(name);
                            if (sqf != null) {
                                downlinkFreq = sqf.getDownlinkHz();
                                uplinkFreq = sqf.getUplinkHz();

                                inverting =  sqf.isRev();
                            }

                            Satellite s = new Satellite(name, line1, line2, uplinkFreq, downlinkFreq, inverting);
                            satelliteMap.put(name, s);

                        }
                        name = null;
                        line1 = null;
                        line2 = null;
                    } else {
                        name = line;
                    }
                    line = br.readLine();
                }
            } catch (IOException ex) {
                Logger.getLogger(SatelliteDirectory.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
                if (br != null) {
                    try {
                        br.close();
                    } catch (IOException ex) {
                        Logger.getLogger(SatelliteDirectory.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }

        }

    }

    /**
     * Returns the satellite with the given name, or null if none exists with 
     * that name in the directory.
     * 
     * @param name the name of the satellite as referenced in the TLE and SQF 
     * files.
     * @return the satellite or null if none exists in the directory 
     */
    public Satellite getSatellite(String name) {
        return satelliteMap.get(name);
    }
    
    private void loadSqf() throws FileNotFoundException {
        sqfParser.parse();
    }
}
