package gov.va.cpe.vpr.queryeng.dynamic.columns;

import gov.va.cpe.vpr.Order;
import gov.va.cpe.vpr.Result;
import gov.va.cpe.vpr.Task;
import gov.va.cpe.vpr.frameeng.Frame;
import gov.va.cpe.vpr.frameeng.FrameJob;
import gov.va.cpe.vpr.frameeng.FrameRegistry;
import gov.va.cpe.vpr.queryeng.RenderTask;
import gov.va.hmp.healthtime.format.HL7DateTimeFormat;
import gov.va.hmp.healthtime.format.PointInTimeFormat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.*;

import static gov.va.cpe.vpr.queryeng.ViewDef.ViewRenderAction;

/**
 * This class is a complex case.
 * 1) If no CAT scan orders have been placed within (default time, or user spec'ed time) for this patient:
 * 		- Return action advice for creating 
 * @author vhaislchandj
 *
 */
@Component(value = "gov.va.cpe.vpr.queryeng.dynamic.columns.MRIStatus")
@Scope("prototype")
public class MRIStatus extends ViewDefDefColDef {
	
	@Autowired
	FrameRegistry registry;

	@Autowired
	ApplicationContext ctx;

    public MRIStatus() {
    	super(null);
    }
    
    public MRIStatus(Map<String, Object> vals) {
		super(vals);
	}
	
	@PostConstruct
	public void init() {
		fieldName = "MRI Scan";
		getViewdefFilters().put("range", "-1mo");
		getConfigProperties().put("range", "-7d..+1y");
	}

	public ArrayList<String> getFilterDescription() {
		ArrayList<String> filterDesc = new ArrayList<String>();
		filterDesc.add("Rad. Date Range: "+viewdefFilters.get("range"));
		filterDesc.add("Order Date Range: "+configProperties.get("range"));
		return filterDesc;
	}
	
	@Override
	public String getViewdefCode() {
		/**
		 * Here's where we might plug in a frame.. or something with some input/output logic?
		 * Multiple chained frames or viewdefs?
		 * Need to learn more about the frame concept, work with BB on that.
		 */
		return "gov.va.cpe.vpr.queryeng.ProceduresViewDef";
	}

	@Override
	public String getRenderClass() {
		return "brList";
	}

	@Override
	public String getName() {
		return "MRI Scan";
	}
	
	// Mandatory Imaging filter
	@Override
	public Map<String, Object> getViewdefFilters() {
		viewdefFilters.put("qfilter_kind", "Imaging");
		return viewdefFilters;
	}
	
	public List<Config> getViewdefFilterOptions() {
		ArrayList<Config> opts = new ArrayList<Config>();
		Config conf = new Config();
		conf.setName("range");
		conf.setLabel("Imaging reports within");
		opts.add(conf);
		return opts;
	}
	
	public List<Config> getConfigOptions() {
		ArrayList<Config> opts = new ArrayList<Config>();
		Config conf = new Config();
		conf.setName("range");
		conf.setLabel("Orders within");
		opts.add(conf);
		conf = new Config();
		conf.setName("site");
		conf.setLabel("Site");
		opts.add(conf);
		return opts;
	}

	@Override
	public String getDescription() {
		return "MRI scan results (based on Imaging Reports) within the specified time period. If no results found, " +
				"any orders (again within the specified time period) of type 'MRI'. If no orders found, provides an " +
				"action link to create a Task of type 'Order'.";
	}

	public ArrayList<String> getDomainClasses() {
		ArrayList<String> rslt = new ArrayList<String>();
		rslt.add(Task.class.getSimpleName());
		rslt.add(Order.class.getSimpleName());
		rslt.add(Result.class.getSimpleName());
		return rslt;
	}

    @Override
    public Map<String, Object> runDeferred(DeferredBoardColumnTask dtask) {
        Map<String, Object> result = new HashMap<String, Object>();
        ArrayList<String> results = new ArrayList<String>();
        try {
            Map<String, Object> params = new HashMap<>();
            params.putAll(this.getViewdefFilters());
            params.put("pid", dtask.roe.get("pid"));

            FrameJob job = dtask.runner.exec(getViewdefCode(), params);
            RenderTask task = job.getAction(ViewRenderAction.class).getResults();

            Iterator<Map<String, Object>> iter = task.iterator();
            boolean found = false;

            String site = null;
            if(configProperties.get("site")!=null && !configProperties.get("site").equals("")) {site = configProperties.get("site").toString();}

            while(iter.hasNext()) {
                Map<String, Object> itm = iter.next();
                if(itm.get("imagingTypeUid")!=null && itm.get("imagingTypeUid").equals("urn:va:imaging-Type:MAGNETIC RESONANCE IMAGING")) {
                    if(site==null || (itm.get("summary").toString().toLowerCase().contains(site.toLowerCase()))) {
                        found = true;
                        results.add("("+itm.get("statusName").toString()+"): "+itm.get("summary").toString()+"<br>");
                    }
                }
            }
            if(!found) {
                // Need to render a different viewdef - looking for pending orders.

                configProperties.put("filter_group", "MRI");
                configProperties.put("pid", params.get("pid"));

                task = dtask.runner.exec("gov.va.cpe.vpr.queryeng.OrdersViewDef", configProperties).getAction(ViewRenderAction.class).getResults();
                iter = task.iterator();
                while(iter.hasNext()) {
                    Map<String, Object> itm = iter.next();
                    if(site==null || (itm.get("name").toString().toLowerCase().contains(site.toLowerCase()))) {
                        found = true;
                        results.add("Ordered for: "+ PointInTimeFormat.dateTime().print(HL7DateTimeFormat.parse(itm.get("start").toString()))+"<br>");
                    }
                }
                if(!found) {
					/*
					 * This is a blatantly ugly hack that is just intended as a proof of concept.
					 * The column really wants to play a dual role, as both an action and informational column.
					 *
					 * A.K.A. "Black Magic part 1 of 2"
					 */
                    results.add("<a href=\"javascript:;\" onmousedown=\"gov.va.cpe.TaskWindow.showTaskForPatient(event, "+params.get("pid")+")" +
                            "\">Add Task</a><br>");
                }
            }
        } catch (Frame.FrameExecException e) {
            e.printStackTrace();
            results.add("Error: " + e.getMessage());
            log.error("Cannot render MRIStatus: "+e.getMessage(), e);
        } catch (Frame.FrameInitException e) {
            e.printStackTrace();
            results.add("Error: " + e.getMessage());
            log.error("Cannot render MRIStatus: "+e.getMessage(), e);
        }

        result.put("results",results);
        return result;
    }
}
