/*
 * LocCanvas.java
 *
 * Created on 19 ottobre 2005, 9.16
 */
import javax.microedition.lcdui.*;
import com.motorola.location.*;

/**
 *
 * @author Enrico Bertozzi
 */
public class LocCanvas extends Canvas implements Runnable, PositionListener{
    private PositionSource lcon;
    public Thread loct;
    private Font normal,bold;
    public boolean bTerminate = false;
    public boolean bInstantiationError = false;
    private PositionData pdat = new PositionData();
    
    private boolean bNewPos = true;
    private int Accuracy, Timeout, Age;
    private int wp = 0;
    private int nFix = 0, nReq = 0;
    private final float conversion = (float)6000000;

    
    public LocCanvas(PositionSource a, int nacc, int ntim, int nage) 
    {
        lcon = a;
        Accuracy = nacc;
        Timeout = ntim;
        Age = nage;
        loct = new Thread(this);
        normal = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
        bold = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_BOLD, Font.SIZE_SMALL);
    }
    
    synchronized public void paint(Graphics g)
    {
        PositionData pdt = new PositionData(pdat);
        
        
        g.setColor(255,255,255);
        g.fillRect(0, 0, this.getWidth(), this.getHeight());
        
        g.setFont(normal);
        g.setColor(0);
        g.drawString("Status:", 5, 5, g.LEFT | g.TOP);
        g.setColor(255,0,0);
        if (lcon==null)
        {
            if (bInstantiationError)
                g.drawString("GPS unauthorizated or not found!", 5, 20, g.LEFT | g.TOP);
            else
                g.drawString("Class initialization", 5, 20, g.LEFT | g.TOP);
        }
        else
        {
            //String wait = new String("Waiting");
            String latlon;
            int i;
            g.drawString(statusString(lcon.getStatus()), 5, 20, g.LEFT | g.TOP);
            
            g.setColor(0);
            g.setFont(bold);

            if (pdt.Latitude == AggregatePosition.UNAVAILABLE)
                g.drawString("Lat unknown",10, 50, g.LEFT | g.TOP);
            else
            {
                latlon = arcminToString(pdt.Latitude);
                if (pdt.Latitude>0) latlon=latlon.concat("N"); else latlon=latlon.concat("S");
                g.drawString("Lat " + latlon,10, 50, g.LEFT | g.TOP);
            }

            if (pdt.Longitude == AggregatePosition.UNAVAILABLE)
                g.drawString("Lon unknown",10, 65, g.LEFT | g.TOP);
            else
            {
                latlon = arcminToString(pdt.Longitude);
                if (pdt.Latitude>0) latlon=latlon.concat("E"); else latlon=latlon.concat("W");
                g.drawString("Lon " + latlon,10, 65, g.LEFT | g.TOP);
            }

            if (pdt.Altitude == AggregatePosition.UNAVAILABLE)
                g.drawString("Alt unknown",10, 80, g.LEFT | g.TOP);
            else
                g.drawString("Alt " + Integer.toString(pdt.Altitude) + "m",10, 80, g.LEFT | g.TOP);
         
            // mm/s
            if (pdt.Speed == AggregatePosition.UNAVAILABLE)
                g.drawString("Speed unknown",10, 100, g.LEFT | g.TOP);
            else
                g.drawString("Speed " + Integer.toString((int)(pdt.Speed * (float)0.0036)) + " km/h",10, 100, g.LEFT | g.TOP);
            
            if (pdt.PointingDirection == AggregatePosition.UNAVAILABLE)
                g.drawString("Direction unknown",10, 115, g.LEFT | g.TOP);
            else
                g.drawString("Direction " + degToCardinals(pdt.PointingDirection),10, 115, g.LEFT | g.TOP);            
            
                
            
//            if (++wp > 3) wp = 1;
//            for (i=0; i<wp; i++)
//                wait=wait.concat(".");
//
//            g.drawString(wait , getWidth()-5,5, g.RIGHT | g.TOP);
            g.setColor(128,128,128);
            g.setFont(normal);
            g.drawString("GPS RQD: " + Integer.toString(nReq) , 5,145, g.LEFT | g.TOP);
            g.drawString("GPS RSP: " + Integer.toString(nFix) , 5,160, g.LEFT | g.TOP);
        }
    }
    
    synchronized public void run()
    {
        while (!bTerminate)
        {
            try{
                this.wait(1000);
            } catch (Exception e) {}

            if (bNewPos || lcon.getStatus() != PositionSource.POSITION_OK)
            {
                bNewPos = false;
                lcon.generatePosition(Accuracy, Age, Timeout);
                nReq++;
            }

            this.repaint();
        }
    }
    
    synchronized public void newPosition(AggregatePosition pos)
    {
        nFix++;
        bNewPos = true;
        
        if (lcon.getStatus() == PositionSource.POSITION_OK)
        {
            pdat.Latitude = pos.getLatitude();
            pdat.Longitude = pos.getLongitude();
            pdat.Altitude = pos.getAltitude() - 35;     // Correzione errore
            pdat.Accuracy = pos.getLatLonAccuracy();
            pdat.PointingDirection = pos.getPointingDirection();
            pdat.Speed = pos.getSpeed();
            
        }
    }
    
    private String statusString(int status)
    {
        switch (status)
        {
            case PositionSource.ERR_GPS_DISABLED_BY_USER:
                return "GPS disabled";
            case PositionSource.ERR_GPS_NOT_PRESENT:
                return "GPS not present";
            case PositionSource.ERR_INTERNAL:
                return "Internal error";
            case PositionSource.ERR_NOT_ENOUGH_SAT:
                return "Too few satellites";
            case PositionSource.ERR_NO_RESPONSE:
                return "No response";
            case PositionSource.ERR_RECEIVER:
                return "Receiver error";
            case PositionSource.ERR_TIMEOUT:
                return "GPS timeout";
            case PositionSource.ERR_UNAVAILABLE:
                return "GPS unavailable";
            case PositionSource.POSITION_OK:
                return "GPS running";
            default:
                return "Unknown status (" + Integer.toString(status) + ")";
        }
    }
    
    private String arcminToString(int arcmin)
    {
        float deg = (float)arcmin / conversion;
        int g1,pp;
        float g2;
        String g3;
        
        g1 = (int)deg;
        g2 = (deg - (int)deg) * 60;
        g3 = Float.toString((g2 - (int)g2) * 60);
        if ((pp = g3.indexOf('.')) != -1)
        {
            if (g3.length() - pp < 2)
                g3 = g3.concat("0");
            else if (g3.length() - pp > 2)
                g3 = g3.substring(0, pp+3);
        }
        else 
            g3 = g3.concat(".00");
        
        return new String(Integer.toString(g1) + "° " + Integer.toString((int)g2) + "' " + g3 + "'' ");
        
    }
    
    private String degToCardinals(int deg)
    {
        if (deg <= 22500 || deg > 337500)
            return "N";
        else if (deg <= 67500)
            return "NE";
        else if (deg <= 112500)
            return "E";
        else if (deg <= 157500)
            return "SE";
        else if (deg <= 202500)
            return "S";
        else if (deg <= 247500)
            return "SW";
        else if (deg <= 292500)
            return "W";
        else 
            return "NW";
    }
}
