import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import net.learntechnology.visitordemo.visitable.Department;
import net.learntechnology.visitordemo.visitable.Employee;
import net.learntechnology.visitordemo.visitable.Job;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class UglyNonVisitorWay {
	
	Document doc;
	StringBuilder xmlBuilder = null;
	 
    public static void main(String[] args) {
        UglyNonVisitorWay ugly = new UglyNonVisitorWay();
        ugly.doIt();
    }
    
    private void doIt() {
        Department dept = new Department("Main Department");
        dept.setDepartments(Util.getDepartments());
        Element deptElm = null;
        Element deptsElm = null;
        for( FormatType formatType: FormatType.values() ) {
        	System.out.println("\n-----------"+ formatType +"-----------------");
	        switch(formatType) {
		    	case DOM:
		    		if ( formatType == FormatType.DOM ) {
		    	        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		    	        try {
		    	            DocumentBuilder builder = factory.newDocumentBuilder();
		    	            doc = builder.newDocument();
		    	            deptElm = doc.createElement("department");
		    	            deptElm.setAttribute("name", dept.getDepartmentName());
		    	            doc.appendChild(deptElm);
		    	            deptsElm = doc.createElement("departments");		    	            
		    	        } catch (Exception e) {
		    	            e.printStackTrace();
		    	        }
		            } 
		    		break;
		    	case XML:
		    		xmlBuilder = new StringBuilder("\n");
		    		xmlBuilder.append(pad("\n",4));
		    		break;
		    	default:
		    		System.out.println("Department: Main Department");
		    }
	        recurseDepartments(formatType, dept.getDepartments().iterator(), 8, deptsElm);
	        switch(formatType) {
			    case DOM:
			    	deptElm.appendChild(deptsElm);
			    	System.out.println(Util.getDOMasXML(doc));
					break;
				case XML:
					xmlBuilder.append(pad("\n",4));
					xmlBuilder.append("");
					System.out.println(xmlBuilder.toString());
					break;
		    }
        }
    }
    
    private void recurseDepartments( FormatType formatType, Iterator iter, int padAmnt, Element deptsElm ) {
        if ( iter.hasNext() ) {
            Department department = (Department)iter.next();
            Element deptElm = null;
            switch(formatType) {
	        	case DOM:
	        		deptElm = doc.createElement("department");
	        		deptElm.setAttribute("name", department.getDepartmentName());
	        		break;
	        	case XML:
	        		xmlBuilder.append(pad("\n", padAmnt));
	        		break;
	        	default:
	        		System.out.println(pad("Department: "+department.getDepartmentName(), padAmnt ));
	        }
            //display employees and any jobs they have
            int empPad = padAmnt+4;
            for( Employee emp: department.getEmployees()) {
                Element empElm = null;
                switch(formatType) {
		        	case DOM:
		        		empElm = doc.createElement("employee");
		        		empElm.setAttribute("name", emp.getEmployeeName());
		        		break;
		        	case XML:
		        		xmlBuilder.append(pad("\n",empPad));
		        		break;
		        	default:
		        		System.out.println(pad("Employee: "+emp.getEmployeeName(), empPad ));
		        }
                int jobPad = empPad + 4;
                for ( Job job: emp.getJobs() ) {
					Element jobElm = null;
					switch(formatType) {
			        	case DOM:
			        		jobElm = doc.createElement("job");
			        		jobElm.setAttribute("code", job.getJobCode());
							jobElm.setAttribute("description", job.getJobDescription());   
							empElm.appendChild(jobElm);
							break;
			        	case XML:
			        		xmlBuilder.append(pad("\n",jobPad));
			        		break;
			        	default:
			        		System.out.println(pad("jobCode: "+job.getJobCode()+", jobDescription: "+job.getJobDescription() , jobPad));
			        }
                }
                switch(formatType) {
		        	case DOM:
		        		deptElm.appendChild(empElm);
		        		break;
		        	case XML:
		        		xmlBuilder.append(pad("\n", empPad));
		        		break;
		        }
            }
            if (!department.getDepartments().isEmpty()) {
            	Element subDeptsElm = null;
            	switch(formatType) {
		        	case DOM:
		        		subDeptsElm = doc.createElement("departments");
						break;
		        	case XML:
		        		xmlBuilder.append(pad("\n",padAmnt+4));
		        		break;
		        }
            	recurseDepartments(formatType, department.getDepartments().iterator(), padAmnt+8, subDeptsElm);
            	switch(formatType) {
		        	case DOM:
						break;
		        	case XML:
		        		xmlBuilder.append(pad("\n",padAmnt+4));
		        		break;
		        }
			}
            switch(formatType) {
	        	case DOM:
	        		deptsElm.appendChild(deptElm);
	        		break;
	        	case XML:
	        		xmlBuilder.append(pad("\n", padAmnt));
	        		break;
	        }
            recurseDepartments(formatType, iter, padAmnt, deptsElm);
        }
    }
    private String pad(String s, int padAmnt ) {
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < padAmnt; i++) {
            builder.append(" ");
        }
        builder.append(s);
        return builder.toString();
    }
}

enum FormatType {
    CONSOLE, XML, DOM;
}