package com.smartgwt.sample.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Date;  
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.FormItemCriterionGetter;
import com.smartgwt.client.widgets.form.fields.CheckboxItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.RelativeDateItem;
import com.smartgwt.client.widgets.form.fields.RichTextItem;
import com.smartgwt.client.widgets.form.fields.SelectItem;
import com.smartgwt.client.widgets.form.fields.TextItem;
import com.smartgwt.client.widgets.form.fields.events.ChangedEvent;
import com.smartgwt.client.widgets.form.fields.events.ChangedHandler;
import com.smartgwt.client.widgets.grid.ListGridRecord;
import com.smartgwt.client.widgets.grid.events.CellClickEvent;
import com.smartgwt.client.widgets.grid.events.CellClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;
import com.smartgwt.client.widgets.layout.LayoutSpacer;
import com.smartgwt.client.widgets.layout.VLayout;
import com.smartgwt.client.widgets.layout.VStack;
import com.smartgwt.client.widgets.tree.Tree;
import com.smartgwt.client.widgets.tree.TreeGrid;
import com.smartgwt.client.widgets.tree.TreeNode;


import java.util.Date;

import com.smartgwt.client.data.AdvancedCriteria;
import com.smartgwt.client.data.Criteria;
import com.smartgwt.client.data.Criterion;
import com.smartgwt.client.data.DSCallback;
import com.smartgwt.client.data.DSRequest;
import com.smartgwt.client.data.DSResponse;
import com.smartgwt.client.data.DataSource;
import com.smartgwt.client.data.Record;
import com.smartgwt.client.data.RecordList;
import com.smartgwt.client.data.RelativeDate;
import com.smartgwt.client.rpc.RPCManager;
import com.smartgwt.client.rpc.RPCRequest;
import com.smartgwt.client.types.Alignment;  
import com.smartgwt.client.types.AutoFitWidthApproach;
import com.smartgwt.client.types.AutoSelectionModel;
import com.smartgwt.client.types.Autofit;
import com.smartgwt.client.types.DSOperationType;
import com.smartgwt.client.types.EmbeddedPosition;
import com.smartgwt.client.types.ListGridComponent;
import com.smartgwt.client.types.ListGridEditEvent;
import com.smartgwt.client.types.ListGridFieldType;
import com.smartgwt.client.types.MultipleAppearance;
import com.smartgwt.client.types.OperatorId;
import com.smartgwt.client.types.Overflow;
import com.smartgwt.client.types.RecordComponentPoolingMode;
import com.smartgwt.client.types.RelativeDateRangePosition;
import com.smartgwt.client.types.RowEndEditAction;
import com.smartgwt.client.types.SelectionAppearance;
import com.smartgwt.client.types.SelectionStyle;
import com.smartgwt.client.types.TextMatchStyle;
import com.smartgwt.client.types.TimeUnit;
import com.smartgwt.client.types.TitleOrientation;
import com.smartgwt.client.types.VerticalAlignment;
import com.smartgwt.client.util.DateUtil;
import com.smartgwt.client.util.JSOHelper;
import com.smartgwt.client.util.JSON;
import com.smartgwt.client.util.JSONEncoder;
import com.smartgwt.client.util.Page;
import com.smartgwt.client.util.SC;
import com.smartgwt.client.widgets.Canvas;  
import com.smartgwt.client.widgets.IButton;
import com.smartgwt.client.widgets.Label;
import com.smartgwt.client.widgets.TransferImgButton;
import com.smartgwt.client.widgets.cube.CubeGrid;
import com.smartgwt.client.widgets.cube.Facet;
import com.smartgwt.client.widgets.cube.FacetValue;
import com.smartgwt.client.widgets.cube.FacetValueMap;
import com.smartgwt.client.widgets.events.ClickEvent;  
import com.smartgwt.client.widgets.events.ClickHandler;  
import com.smartgwt.client.widgets.events.DrawEvent;
import com.smartgwt.client.widgets.events.DrawHandler;
import com.smartgwt.client.widgets.events.VisibilityChangedEvent;
import com.smartgwt.client.widgets.events.VisibilityChangedHandler;
import com.smartgwt.client.widgets.grid.HeaderSpan;
import com.smartgwt.client.widgets.grid.ListGrid;  
import com.smartgwt.client.widgets.grid.ListGridEditorContext;
import com.smartgwt.client.widgets.grid.ListGridEditorCustomizer;
import com.smartgwt.client.widgets.grid.ListGridField;  
  
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.regexp.shared.RegExp;
import com.google.gwt.user.client.Timer;  
  

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class BuiltInDS implements EntryPoint {
	private String json;
	public static native void logToSC(String msg) /*-{
	$wnd.isc.logWarn(msg);
}-*/;

	public void onModuleLoad() {

      

      RPCManager.sendRequest(createGetJSonReq(), (response, rawData, request) -> {
          if (response.getStatus() < 0 || rawData == null) {
        	  // could not get file
        	  logToSC("Could not get json file");
               return;
          }
          json = rawData.toString();
          createTreeGrid();
      }); 
      
	}
	
	private void createTreeGrid() {
		  Canvas canvas = new Canvas();
		  canvas.setWidth100();
		  canvas.setHeight100();
		  
		 List<String> list = (List<String>)JSOHelper.convertToList(JSON.decode(json));
	      
	      List<TreeNode> nodes = new ArrayList<TreeNode>();
	      
	      for (String str : list) {
	    	  Map<String, Object> map = (Map<String, Object>)JSOHelper.convertToMap(JSON.decode(str));
	    	  TreeNode node = new TreeNode();
	    	  for (String key : map.keySet()) {
	    		  if (key.contains("children")) {
	    			  continue;
	    		  }
	    		  node.setAttribute(key, map.get(key));
	    	  }

	    	  nodes.add(node);
	      }
	      
	      TreeNode[] nodeArr = new TreeNode[nodes.size()];
	      nodeArr = nodes.toArray(nodeArr);
	      
	      TreeGrid drvDetailGrid = new TreeGrid();
	      drvDetailGrid.setDataSource(DataSource.get("ChipSTA_ChipDRVDetails"));
	      Tree tree = new Tree();
	      tree.setIdField("Level_Id");
	      tree.setParentIdField("Parent_Id");
	      tree.linkNodes(nodeArr);
	      
	      drvDetailGrid.setData(tree);
	      drvDetailGrid.setAutoFitData(Autofit.BOTH);
	      drvDetailGrid.setWidth100();
	      drvDetailGrid.setHeight100();
	      
	      
	      
	      // our options are set below - still slow when these are disabled
			drvDetailGrid.setHeaderSpans(getHeaderSpans());
			drvDetailGrid.setUseAllDataSourceFields(true);

			drvDetailGrid.setVirtualScrolling(false);
			drvDetailGrid.setCanExpandRecords(false);
			drvDetailGrid.setShowAllRecords(true);
			drvDetailGrid.setShowRecordComponents(false);
			drvDetailGrid.setShowRecordComponentsByCell(false);
			drvDetailGrid.setAnimateFolderSpeed(6000);
			drvDetailGrid.setTreeRootValue("-1");
			drvDetailGrid.setFolderIcon(null);
			drvDetailGrid.setCanFreezeFields(false);
			drvDetailGrid.setNodeIcon(null);
			
			drvDetailGrid.setUseAllDataSourceFields(true);
			drvDetailGrid.setWidth100();
			drvDetailGrid.setAutoFitFieldWidths(false);
			drvDetailGrid.setAutoFitFieldsFillViewport(true);
			drvDetailGrid.setMinFieldWidth(30);
			drvDetailGrid.setAutoFitWidthApproach(AutoFitWidthApproach.BOTH);
			drvDetailGrid.setShowGridSummary(true);
			
			drvDetailGrid.setAutoSizeHeaderSpans(true);

			drvDetailGrid.setBodyOverflow(Overflow.HIDDEN);
			drvDetailGrid.setOverflow(Overflow.HIDDEN);
			drvDetailGrid.setCanFocus(false);
			drvDetailGrid.setCanHover(true);
			drvDetailGrid.setCanGroupBy(false);
			drvDetailGrid.setCanMultiGroup(false);
			drvDetailGrid.setRecordComponentPosition(EmbeddedPosition.WITHIN);
			drvDetailGrid.setLeaveHeaderMenuButtonSpace(false);
			drvDetailGrid.setRecordComponentPoolingMode(RecordComponentPoolingMode.DATA);
			drvDetailGrid.setAutoSizeHeaderSpans(true);
			drvDetailGrid.setCellPadding(8);

			
		  canvas.addChild(drvDetailGrid);

	      canvas.draw();  
	      
	}
    private RPCRequest createGetJSonReq () {

        String appDirectory = Page.getAppDir();
        
        RPCRequest request = new RPCRequest();
        request.setActionURL(appDirectory+"JsonTreeGridRecords.txt");
        request.setHttpMethod("GET");
        request.setBypassCache(true);
        request.setWillHandleError(true);
        return request;
    }
    
	public static HeaderSpan[] getHeaderSpans() {
		return getHeaderSpans("", "");
	}
	public static HeaderSpan[] getClockMatrixHeaderSpans() {
		return new HeaderSpan[] {
			new HeaderSpan("Setup (ns)", new String[] { "SetupWNS", "SetupTNS", "SetupNumPaths", "SetupWorstMode", "SetupWorstCorner", "SetupEndPoint"}),
			new HeaderSpan("Hold (ns)", new String[] { "HoldWNS", "HoldTNS", "HoldNumPaths", "HoldWorstMode", "HoldWorstCorner", "HoldEndPoint" }),
		};
		
	}
		
	public static HeaderSpan[] getHeaderSpans(String holdAnalysis, String setupAnalysis) {
		String holdAnalysisText = holdAnalysis.length() > 0 ? " : <span style='color: yellow'>" + holdAnalysis +"</span>" :  "";
		String setupAnalysisText = holdAnalysis.length() > 0 ? " : <span style='color: yellow'>" + setupAnalysis +"</span>": "";

		return new HeaderSpan[] {
				new HeaderSpan("Setup (ns)" + setupAnalysisText, new String[] { "SetupWNS", "PredictedSetupWNS", "SetupWNSToPeriod", "SetupTNS", "PredictedSetupTNS",
							"SetupNumPaths", "PredictedSetupNumPaths", "WorstSetupNumPaths", "SetupUncertainty", "SetupPeriod", "SetupAnalysisMode", "SetupWNSPathClkSkew", "SetupClockFrequency", "SetupClockRiseFall" }),
				new HeaderSpan("Hold (ns)" + holdAnalysisText, new String[] { "HoldWNS", "PredictedHoldWNS", "HoldTNS", "PredictedHoldTNS", "HoldNumPaths", 
						"PredictedHoldNumPaths", "WorstHoldNumPaths", "HoldUncertainty", "HoldAnalysisMode", "HoldWNSPathClkSkew", "HoldClockRiseFall" }),
				new HeaderSpan("Max Transition (ns)", new String[] { "MaxTransitionWNS","PredictedMaxTransitionWNS", "MaxTransitionTNS","PredictedMaxTransitionTNS", "MaxTransitionNumPaths","PredictedMaxTransitionNumPaths", "MaxTransitionViolsWaived", "PredictedMaxTransitionViolsWaived", "MaxTransitionNumDrivers","PredictedMaxTransitionNumDrivers"   }),
				new HeaderSpan("Max Fanout", new String[] { "MaxFanoutWNS","PredictedMaxFanoutWNS", "MaxFanoutTNS","PredictedMaxFanoutTNS", "MaxFanoutNumPaths","PredictedMaxFanoutNumPaths", "MaxFanoutViolsWaived", "PredictedMaxFanoutViolsWaived"}),
				new HeaderSpan("Clock Transition Rise (ns)", new String[] { "ClockTransitionRiseWNS", "ClockTransitionRiseTNS", "ClockTransitionRiseNumPaths", "ClockTransitionRiseViolsWaived", "ClockTransitionRiseNumDrivers",
						"PredictedClockTransitionRiseWNS", "PredictedClockTransitionRiseTNS", "PredictedClockTransitionRiseNumPaths", "PredictedClockTransitionRiseViolsWaived", "PredictedClockTransitionRiseNumDrivers"}),
				new HeaderSpan("Clock Transition Fall (ns)", new String[] { "ClockTransitionFallWNS", "ClockTransitionFallTNS", "ClockTransitionFallNumPaths", "ClockTransitionFallViolsWaived", "ClockTransitionFallNumDrivers",
						"PredictedClockTransitionFallWNS", "PredictedClockTransitionFallTNS", "PredictedClockTransitionFallNumPaths", "PredictedClockTransitionFallViolsWaived", "PredictedClockTransitionFallNumDrivers"}),
				// new HeaderSpan("Clock Transition (fall)", new String[]{"ClkTranFallWNS","ClkTranFallTNS","ClkTranFallNumPaths"}),
				new HeaderSpan("Max Capacitance (pF)", new String[] { "MaxCapacitanceWNS","PredictedMaxCapacitanceWNS", "MaxCapacitanceTNS","PredictedMaxCapacitanceTNS", "MaxCapacitanceNumPaths", "PredictedMaxCapacitanceNumPaths", "MaxCapacitanceViolsWaived","PredictedMaxCapacitanceViolsWaived"}),
				new HeaderSpan("Min Period (ns)", new String[] { "MinPeriodWNS","PredictedMinPeriodWNS", "MinPeriodTNS","PredictedMinPeriodTNS",  "MinPeriodNumPaths","PredictedMinPeriodNumPaths",  "MinPeriodViolsWaived", "PredictedMinPeriodViolsWaived"}),
				new HeaderSpan("Min Pulse Width (ns)", new String[] { "MinPulseWidthWNS", "MinPulseWidthTNS", "MinPulseWidthNumPaths", "MinPulseWidthViolsWaived",
						"PredictedMinPulseWidthWNS", "PredictedMinPulseWidthTNS", "PredictedMinPulseWidthNumPaths", "PredictedMinPulseWidthViolsWaived"}),
				new HeaderSpan("Noise (mV)", new String[] { "NoiseWNS","PredictedNoiseWNS", "NoiseTNS","PredictedNoiseTNS", "NoiseNumPaths", "PredictedNoiseNumPaths", "NoiseViolsWaived", "PredictedNoiseViolsWaived"}) ,
				new HeaderSpan("Double Clocking (mV)", new String[] { "DoubleClockingWNS", "DoubleClockingTNS", "DoubleClockingNumPaths", "DoubleClockingViolsWaived", "DoubleClockingNumDrivers",
						"PredictedDoubleClockingWNS", "PredictedDoubleClockingTNS", "PredictedDoubleClockingNumPaths", "PredictedDoubleClockingViolsWaived", "PredictedDoubleClockingNumDrivers"}) ,
				new HeaderSpan("DRV", new String[] { "DRVWNS", "DRVTNS", "DRVNumPaths", "DRVViolsWaived", "DRVNumDrivers" }) };
	}
	public static HeaderSpan[] getSummaryHeaderSpans() {
		HeaderSpan setup  = new HeaderSpan();
		setup.setTitle("Setup (ns)");
		setup.setSpans(
				new HeaderSpan("(SP) Inter-Block", new String[]{"SPInterSetupWNS","SPInterSetupTNS","SPInterSetupNumPaths"}),
				new HeaderSpan("(EP) Inter-Block", new String[]{"EPInterSetupWNS","EPInterSetupTNS","EPInterSetupNumPaths"}),
				new HeaderSpan("Intra-Block", new String[]{"EPIntraSetupWNS","EPIntraSetupTNS","EPIntraSetupNumPaths"})
		);
		HeaderSpan hold  = new HeaderSpan();
		hold.setTitle("Hold (ns)");
		hold.setSpans(
				new HeaderSpan("(SP) Inter-Block", new String[]{"SPInterHoldWNS","SPInterHoldTNS","SPInterHoldNumPaths"}),
				new HeaderSpan("(EP) Inter-Block", new String[]{"EPInterHoldWNS","EPInterHoldTNS","EPInterHoldNumPaths"}),
				new HeaderSpan("Intra-Block", new String[]{"EPIntraHoldWNS","EPIntraHoldTNS","EPIntraHoldNumPaths"})
		);
		
		HeaderSpan eco  = new HeaderSpan("ECO Changes", new String[]{"Total_Resizes","Total_Inserts"});
		return new HeaderSpan[] {
				setup,hold,
				new HeaderSpan("DRV", new String[] { "DRVWNS", "DRVTNS", "DRVNumPaths", "DRVViolsWaived" }), 
				eco
				};
	}
}
