package caseStudy;

import java.util.ArrayList;

public class CrochetPattern extends SaveAsXML {
    // Pattern class
    private SaveableField <String> name;
    private SaveableField <Double> recommendedHookSize;    // Canadian system, in mm
    private SaveableField <Double> actualHookSize;         // Canadian system, in mm
    private SaveableField <Gauge> gauge;    // Used (by the user) to determine actual hook size
    private SaveableField <ArrayList<YarnColour>> colours;
    private SaveableField <ArrayList<Row>> rows;
    private SaveableField <ArrayList<Stitch>> stitchesUsed;
 
    // XML Tags
    public static final String STARTCLASSTAG = "<CrochetPattern>";
    public static final String ENDCLASSTAG = "</CrochetPattern>";
    private static final String STARTYARNLISTTAG = "<YarnColourList>";
    private static final String ENDYARNLISTTAG = "</YarnColourList>";
    private static final String STARTROWLISTTAG = "<RowList>";
    private static final String ENDROWLISTTAG = "</RowList>";
    private static final String STARTSTITCHLISTTAG = "<StitchList>";
    private static final String ENDSTITCHLISTTAG = "</StitchList>";
    
    // Constructors
    public CrochetPattern() {
        initializeFields();
        name.setValue("New Pattern");
        recommendedHookSize.setValue(-1.0);
        actualHookSize.setValue(-1.0);
        gauge.setValue(new Gauge());
        colours.setValue(new ArrayList<YarnColour> (1));
        rows.setValue(new ArrayList<Row> ());
        stitchesUsed.setValue(new ArrayList<Stitch> ());
    }
    public CrochetPattern(CrochetPattern pattern) {
        initializeFields();
        name.setValue(pattern.getName());
        recommendedHookSize.setValue(pattern.getRecommendedHook());
        actualHookSize.setValue(pattern.getActualHook());
        gauge.setValue(new Gauge(pattern.getGauge()));
        colours.setValue(new ArrayList<YarnColour> (pattern.getColours()));
        rows.setValue(new ArrayList<Row> (pattern.getRows()));
        stitchesUsed.setValue(new ArrayList<Stitch> (pattern.getStitches()));
    }
    public CrochetPattern(String xml) {
        initializeFields();
        colours.setValue(new ArrayList<YarnColour> (1));
        rows.setValue(new ArrayList<Row> ());
        stitchesUsed.setValue(new ArrayList<Stitch> ());
        this.load(xml);
    }
    
    //Accessors
    public String getName() {
        return name.getValue();
    }
    public double getRecommendedHook() {
        return recommendedHookSize.getValue();
    }
    public double getActualHook() {
        return actualHookSize.getValue();
    }
    public Gauge getGauge() {
        return gauge.getValue();
    }
    public ArrayList<YarnColour> getColours() {
        return colours.getValue();
    }
    public ArrayList<Row> getRows() {
        return rows.getValue();
    }
    public ArrayList<Stitch> getStitches(){
        return stitchesUsed.getValue();
    }
    public int length() {
        return rows.getValue().size();
    }
    public String save() {
        String toSave = STARTCLASSTAG
                + name.save()
                + recommendedHookSize.save()
                + actualHookSize.save()
                + STARTYARNLISTTAG;
        for(YarnColour yarn : colours.getValue()) {
            toSave = toSave.concat(yarn.save());
        }
        toSave = toSave.concat(ENDYARNLISTTAG + STARTROWLISTTAG);
        for(Row r : rows.getValue()) {
            toSave = toSave.concat(r.save());
        }
        toSave = toSave.concat(ENDROWLISTTAG + STARTSTITCHLISTTAG);
        for(Stitch s : stitchesUsed.getValue()) {
            toSave = toSave.concat(s.save());
        }
        toSave = toSave.concat(ENDSTITCHLISTTAG + ENDCLASSTAG);
        return toSave;
    }
    public String toString() {
        String toPrint = "Pattern Name: " + name.getValue() + "\n\tRecommended hook size: " + recommendedHookSize.getValue();
        toPrint = toPrint.concat("\n\t" + gauge.getValue());
        toPrint = toPrint.concat("\n\tColours used: ");
        for(YarnColour c : colours.getValue()) {
            toPrint = toPrint.concat("\n\t\t" + c);
        }
        toPrint = toPrint.concat("\n\tStitches used: ");
        for(Stitch s : stitchesUsed.getValue()) {
            toPrint = toPrint.concat("\n\t\t" + s);
        }
        toPrint = toPrint.concat("\n\tPattern Instructions:");
        for(Row r : rows.getValue()) {
            toPrint = toPrint.concat("\n\t\t" + r);
        }
        return toPrint;
    }
    public boolean equals(CrochetPattern p) {
        if((name.getValue() == p.getName()) 
                && (gauge.getValue() == p.getGauge()) 
                && (recommendedHookSize.getValue() == p.getRecommendedHook())
                && (rows.getValue() == p.getRows())
                && (stitchesUsed.getValue() == p.getStitches())) {
            return true;
        }
        return false;
    }
    
    //Modifiers
    public void setName(String newName) {
        name.setValue(newName);
    }
    public void setRecommendedHook(double newHook) {
        recommendedHookSize.setValue(newHook);
    }
    public void setActualHook(double newHook) {
        actualHookSize.setValue(newHook);
    }
    public void setGauge(Gauge newGauge) {
        gauge.setValue(newGauge);
    }
    public void addColour(YarnColour colour) {
        colours.getValue().add(colour);
    }
    public void addColour(String colour, double yardage, double weight, int wraps) {
        colours.getValue().add(new YarnColour(colour, yardage, weight, wraps));
    }
    public void addColour(String colour, double yardage, double weight, int wraps, int weightCat, String weightDesc) {
        colours.getValue().add(new YarnColour(colour, yardage, weight, wraps, weightCat, weightDesc));
    }
    public void addStitch(Stitch stitch) {
        stitchesUsed.getValue().add(stitch);
    }
    public void addStitch(String n, String abbr, String how) {
        stitchesUsed.getValue().add(new Stitch(n, abbr, how));
    }
    public void addStitch(String n, String abbr, String how, Integer w) {
        stitchesUsed.getValue().add(new Stitch(n, abbr, how, w));
    }
    public void newRow() {
        rows.getValue().add(new Row());
    }
    public void newRow(Row r) {
        rows.getValue().add(new Row(r));
    }
    public void newRow(String i, Integer l) {
        rows.getValue().add(new Row(i, l));
    }
    public void load(String xml) {
        name.setValue(name.getStringDataFromXML(xml));
        recommendedHookSize.setValue(Double.parseDouble(recommendedHookSize.getStringDataFromXML(xml)));
        actualHookSize.setValue(Double.parseDouble(actualHookSize.getStringDataFromXML(xml)));
        if (gauge.getStringDataFromXML(xml)!=null) {
            gauge.setValue(new Gauge(gauge.getStringDataFromXML(xml)));
        } else {
            gauge.setValue(null);
        }
        
        String yarnList = SaveAsXML.findInXML(xml, STARTYARNLISTTAG, ENDYARNLISTTAG);
        while (!yarnList.isEmpty()) {
            colours.getValue().add(new YarnColour(SaveAsXML.findInXML(yarnList, YarnColour.STARTCLASSTAG, YarnColour.ENDCLASSTAG)));
            yarnList = removeFirst(yarnList, YarnColour.STARTCLASSTAG, YarnColour.ENDCLASSTAG);
        }
        
        String rowList = SaveAsXML.findInXML(xml, STARTROWLISTTAG, ENDROWLISTTAG);
        while (!rowList.isEmpty()) {
            rows.getValue().add(new Row(SaveAsXML.findInXML(rowList, Row.STARTCLASSTAG, Row.ENDCLASSTAG)));
            rowList = removeFirst(rowList, Row.STARTCLASSTAG, Row.ENDCLASSTAG);
        }
        
        String stitchList = SaveAsXML.findInXML(xml, STARTSTITCHLISTTAG, ENDSTITCHLISTTAG);
        while (!stitchList.isEmpty()) {
            stitchesUsed.getValue().add(new Stitch(SaveAsXML.findInXML(stitchList, Stitch.STARTCLASSTAG, Stitch.ENDCLASSTAG)));
            stitchList = removeFirst(stitchList, Stitch.STARTCLASSTAG, Stitch.ENDCLASSTAG);
        }
    }
    
    // Internal Logic
    private void initializeFields() {
        name = new SaveableField <String> ("name");
        recommendedHookSize = new SaveableField <Double> ("recommendedHookSize");
        actualHookSize = new SaveableField <Double> ("actualHookSize");
        gauge = new SaveableField <Gauge> ("gauge");
        colours = new SaveableField <ArrayList <YarnColour>> ("colours");
        rows = new SaveableField <ArrayList <Row>> ("rows");
        stitchesUsed = new SaveableField <ArrayList <Stitch>> ("stitchesUsed");
    }
}
