import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.text.*;

public class Ziemia extends JFrame implements ActionListener
{
    private double Rr = 6378.245;
    private double Rb = 6356.863;
    private JInputDouble tf1 = new JInputDouble(-90.0,90.0);
    private JInputDouble tf2 = new JInputDouble(-90.0,90.0);
    private JTextArea ta = new JTextArea(20,85);
    private HelpHtml helpPanel = null;
    //------------------------
    public static void main(String[] args)
    {
        try 
        {
            UIManager.LookAndFeelInfo[] info = UIManager.getInstalledLookAndFeels();
            for(int i=0;i<info.length;i++)             
            {
                if(info[i].getName().equals("Nimbus"))
                {
                    UIManager.setLookAndFeel(info[i].getClassName());
                }
            }
        }
        catch(Exception e)
        {
        }	
        new Ziemia();
    }
    //------------------------
    public Ziemia()
    {
        super("Odległo?ć dwóch punktów z jednego południka");
        setLayout(new BorderLayout(2,2));
        JPanel p = new JPanel();
        p.setLayout(new FlowLayout(FlowLayout.LEFT));
        p.add(new JLabel("Szeroko?ci geograficzne (w stopniach):  "));
        p.add(tf1);
        p.add(new JLabel("  "));
        tf2.addActionListener(this);
        p.add(tf2);
        createHelpPanel();
        if(helpPanel!=null)
        {
            p.add(new JLabel("  "));
            JButton b = new JButton(new ImageIcon("resources/Help.gif"));
            b.addActionListener(this);
            b.setActionCommand("Help");
            b.setToolTipText("Wyja?nienia");
            p.add(b);
        }

        add(p,BorderLayout.NORTH);

        Font f=new Font("Monospaced",Font.PLAIN,12);

        ta.setFont(f);
        ta.setEditable(false);
        ta.setText(" Szer. 1  Szer. 2     Sposób 1     Sposób 2     Sposób 3     Sposób 4     Sposób 5\n");
        ta.append(policz(0.0,90.0)+"\n");
        ta.append(policz(0.0,1.0)+"\n");
        ta.append(policz(89.0,90.0)+"\n");
        JScrollPane sp=new JScrollPane(ta);
        add(sp,BorderLayout.CENTER);

        pack();
        setLocationRelativeTo(null);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    //------------------------
    private void createHelpPanel()
    {
        helpPanel = new HelpHtml("resources/Help.html","Opis programu",new Dimension(800,600),true,"resources",this);
        if(!helpPanel.isOk())
        {
            helpPanel = null;
        }
        return;
    }
    //------------------------
    private String policz(double szerokosc1,double szerokosc2)
    {
        String answer = "";
        answer+=" "+String.format("%7.3f",szerokosc1)+"  "+String.format("%7.3f",szerokosc2);
        for (int i=1;i<=5;i++)
        {
            answer+="    "+String.format("%9.3f",distance(szerokosc1,szerokosc2,i));
        }
        return answer;
    }
    //------------------------
    public void actionPerformed(ActionEvent ae)
    {
        String cmd = ae.getActionCommand();
        if(cmd.equalsIgnoreCase("Help"))
        {
       	    if(helpPanel.isVisible())
       	    {
                helpPanel.setExtendedState(NORMAL);
       	    }
       	    else
       	    {
                helpPanel.setVisible(true);
       	    }
            return;
        }
        double s1 = 0.0;
        try
        {
            s1 = Double.parseDouble(tf1.getText());
        }
        catch(Exception e)
        {
            s1 = 0.0;
            tf1.setText("0.0   ");
            tf1.requestFocus();
        }
        double s2=0.0;
        try
        {
            s2 = Double.parseDouble(tf2.getText());
        }
        catch(Exception e)
        {
            s2 = 90.0;
            tf1.setText("90.0  ");
        }
        tf1.requestFocus();
        tf1.selectAll();
        ta.append(policz(s1,s2)+"\n");
    }
    //------------------------
    private double distance(double szerokosc1,double szerokosc2,int sposob)
    {
        switch(sposob)
        {
            case 1:
                return 2*Math.PI*Rr*Math.abs(szerokosc2-szerokosc1)/360.0;
            case 2:
                return 2*Math.PI*Rb*Math.abs(szerokosc2-szerokosc1)/360.0;
            case 3:
                double R = (Rr+Rb)/2.0;
                return 2*Math.PI*R*Math.abs(szerokosc2-szerokosc1)/360.0;
            case 4:
                return policzOdleglosc(szerokosc1,szerokosc2);
            case 5:
                return arc(szerokosc1,szerokosc2);
            default:
                return 0.0;
        }
    }
    //-----------------------
    private double policzOdleglosc(double szerokosc1,double szerokosc2)
    {
        if(szerokosc1*szerokosc2>=0)
        {
            double R = (promien(szerokosc1)+promien(szerokosc2))/2.0;
            return 2*Math.PI*R*Math.abs(szerokosc2-szerokosc1)/360.0;
        }
        else
        {
            double R = (promien(szerokosc1)+Rr)/2;
            double wynik = 2*Math.PI*R*Math.abs(szerokosc1)/360.0;
            R = (promien(szerokosc2)+Rr)/2;
            wynik+=2*Math.PI*R*Math.abs(szerokosc2)/360.0;
            return wynik;
        }
    }
    //------------------------
    private double promien(double szerokosc)
    {
        szerokosc = Math.abs(szerokosc);
        if(szerokosc == 90.0)
        {
            return Rb;
        }
        else
        {
            double tg = Math.tan(Math.toRadians(szerokosc));
            return Rb*Rr*Math.sqrt(1+tg*tg)/Math.sqrt(Rb*Rb+Rr*Rr*tg*tg);
        }
    }
    //------------------------
    private double arc(double szerokosc1,double szerokosc2)
    {
        if (szerokosc1>szerokosc2)
        {
            double pom = szerokosc1;
            szerokosc1 = szerokosc2;
            szerokosc2 = szerokosc1;
        }
        int podzielnik = 1;
        boolean done = false;
        double oldResult = 0.0;
        double result = 0.0;
        while(!done)
        {
            result = lamana(szerokosc1,szerokosc2,podzielnik);
            if(result/oldResult<1.000001)
            {
                done = true;
            }
            podzielnik*=2;
            oldResult = result;
        }
        return result;
    }
    //------------------------
    private double lamana(double szerokosc1,double szerokosc2,int podzielnik)
    {
        double result = 0.0;
        double x1 = 0.0;
        double x2 = 0.0;
        double y1 = 0.0;
        double y2 = 0.0;
        double szerokosc = 0.0;
        double przyrost = (szerokosc2-szerokosc1)/podzielnik;
        double tg = 0.0;
        for(int i=0;i<podzielnik;i++)
        {
            szerokosc = szerokosc1+i*przyrost;
            if(szerokosc == 90.0)
            {
                y1 = Rb;
                x1 = 0.0;
                tg = 1.0/0.0;
            }
            else
            {
                tg = Math.tan(Math.toRadians(szerokosc));
                x1=Rr*Rb/Math.sqrt(Rb*Rb+Rr*Rr*tg*tg);
                y1=tg*x1;
            }
            szerokosc+=przyrost;
            if(szerokosc == 90.0)
            {
                y2 = Rb;
                x2 = 0.0;
                tg = 1.0/0.0;
            }
            else
            {
                tg = Math.tan(Math.toRadians(szerokosc));
                x2 = Rr*Rb/Math.sqrt(Rb*Rb+Rr*Rr*tg*tg);
                y2 = tg*x2;
            }
            result+=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
        }
        return result;
    }
}