//[Update:[Sun Jul 04 IST 2021]]
/*History:
**Tue Oct 29 2019
Started.
**Wed Oct 30 2019
 First working version.
**Wed Jul 22 2020
 Allowing lines to be polylines.
**Sun Jul 04 2021
 Can now refer to vertices by id (or 0-based count, as before).
*/
import java.util.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
import javax.swing.*;

public class Skeleton extends Object3D {
    private String sourceFile;

    private JTextField fFld;
    Vector<Vec3> vList;
    Vector<Edge> eList;
    boolean isCurve;
    private static int count;
    public Skeleton(Screen scr) {
        super(new Pose(scr,0,0,0,0,0,0),scr,"Skel"+count);
        count++;
        vList = new Vector<Vec3>();
        eList = new Vector<Edge>();
        idLst = new HashMap<String, Integer>();
        sourceFile = "";
        fFld = new JTextField(10);

        panel.add(new JLabel("Source: ")); panel.add(fFld);
    }
    protected void updating() {
        if(!sourceFile.equals(fFld.getText())) {
            sourceFile = fFld.getText();
            loadFromFile(sourceFile);
        }
    }


    public void save(PrintWriter pw) {
        pw.format(" %s %f\n",sourceFile);
        pose.save(pw);
    }

    protected void load(Scanner scnr) {
        System.err.println("Loading a skeleton");
        double tmpr,tmph;
        try {
            sourceFile = scnr.next();
            pose.load(scnr);
        }
        catch(Exception ex) {
            System.err.println("Failed to load skeleton");
            ex.printStackTrace(System.err);
            return;
        }
        loadFromFile(sourceFile);
        scr.repaint();
    }

    protected void dump(Camera cam, Pad pad) {
        int n = vList.size();
        Vec2[] tmp = new Vec2[n];
        int i=0;
        //System.err.println("Skeleton dump:");
        for(Vec3 v3 : vList) {
            Vec3 world = pose.wrt(v3);
            tmp[i] = cam.see(world);
            //System.err.println(i+"-th point: "+world+" --> "+tmp[i]);
            i++;
        }
        //System.err.println("-------------");
        pad.startGroup();
        if(isCurve) {
            pad.startPath();
            for(i=0;i<tmp.length;i++) {
                pad.addPoint(tmp[i]);
            }
            pad.endPath();
        }
        else {
            for(Edge e : eList) {
                pad.startPath();
                for(int ind : e.lst)
                    pad.addPoint(tmp[ind]);
                pad.endPath();
            }
        }
        pad.endGroup();
    }
    protected void fillGui() {
        fFld.setText(sourceFile);
    }

    HashMap<String, Integer> idLst;
    
    void loadFromFile(String fname) {
        isCurve = true;
        int vCount = 0;
        try {
            Scanner scnr = new Scanner(new File(fname));
            while(scnr.hasNextLine()) {
                String line = scnr.nextLine();
                //System.err.println(line);
                if(line.startsWith("#") || line.trim().length()==0) continue;
                //System.err.println("Info");
                StringTokenizer st = new StringTokenizer(line);

                String nxt = st.nextToken();
                if(nxt.equals("v")) {
                    //System.err.println("A vertex");
                    double x = Double.parseDouble(st.nextToken());
                    double y = Double.parseDouble(st.nextToken());
                    double z = Double.parseDouble(st.nextToken());
                    vList.add(new Vec3(x,y,z));
                    if(st.hasMoreElements()) 
                        idLst.put(st.nextToken(), vCount);
                    else
                        idLst.put(""+vCount, vCount);                        

                    vCount++;
                }
                else if(nxt.equals("l")) {
                    //System.err.println("A line");
                    isCurve = false;
                    Vector<Integer> lst = new Vector<Integer>();
                    while(st.hasMoreTokens()) {
                        lst.add(idLst.get(st.nextToken()));
                    }
                    eList.add(new Edge(lst));
                }
                
            }
            //showAll();
        }
        catch(Exception ex) {
            ex.printStackTrace(System.err);
        }
    }


    public void showAll() {
        for(Vec3 v : vList)
            System.err.println(v);
        for(Edge e : eList)
            System.err.println(e);
    }
        
    public static void main(String args[]) {
    }
}

class Edge {
    Vector<Integer> lst;
    Edge(Vector<Integer> lst) {
        this.lst = lst;
    }

    public String toString() {
        String str = "";
        for(int i : lst)
            str += " --> "+i;
        return str;
    }
}
