public string CreateJson(PrintDeviceInfoInternal device, LowLevelConfigActivityData data, ref string validationCall, ref Dictionary <string, string> validationValues)
        {
            string jsonString = @"{""printer"": """ + device.Address + @""", ""nvps"":[";

            validationCall = jsonString;
            Type type = typeof(LowLevelConfigActivityData);


            Dictionary <string, string> properties = new Dictionary <string, string>();

            //Reflection Fun?
            foreach (PropertyInfo prop in type.GetProperties())
            {
                if (!prop.Name.Equals("EnableFW"))
                {
                    properties.Add(prop.Name, (string)prop.GetValue(data));
                }
            }

            var loopValues = properties.Where(x => !string.IsNullOrWhiteSpace(x.Value)).Where(x => x.Value != "False");

            if (loopValues.Count() == 0)
            {
                return(string.Empty);
            }

            foreach (var item in properties)
            {
                if (!string.IsNullOrEmpty(item.Value))
                {
                    switch (item.Key)
                    {
                    case "SerialNumberBool":
                        if (item.Value == "False" || string.IsNullOrWhiteSpace(item.Value))
                        {
                            continue;
                        }
                        else
                        {
                            jsonString     += _mappedData.GetNVRAM(item.Key, device.SerialNumber);
                            validationCall += _mappedData.GetValidation("SerialNumber");
                            validationCall += @",";
                            validationValues.Add("SerialNumber", device.SerialNumber);
                        }

                        break;

                    case "ModelNumberBool":
                        if (item.Value == "False" || string.IsNullOrWhiteSpace(item.Value))
                        {
                            continue;
                        }
                        else
                        {
                            jsonString     += _mappedData.GetNVRAM(item.Key, device.ModelNumber);
                            validationCall += _mappedData.GetValidation("ModelNumber");
                            validationCall += @",";
                            validationValues.Add("ModelNumber", device.ModelNumber);
                        }

                        break;

                    case "CRDefSleep":
                        jsonString     += _mappedData.GetCRSleep(item.Value);
                        validationCall += _mappedData.GetValidation(item.Key);
                        validationValues.Add(item.Key, item.Value);
                        validationCall += @",";
                        break;

                    case "RebootCrashMode":
                        jsonString     += _mappedData.keyMapping[item.Key][item.Value];
                        validationCall += _mappedData.GetValidation(item.Key);
                        switch (item.Value)
                        {
                        case "Enable":
                            validationValues.Add(item.Key, "01000000");
                            break;

                        case "Disable":
                            validationValues.Add(item.Key, "00000000");
                            break;

                        default:
                            throw new Exception($@"Unhandled {item.Key} setting detected");
                        }
                        validationCall += @",";
                        break;


                    case "JDIMfgReset":
                        jsonString     += _mappedData.keyMapping[item.Key][item.Value];
                        validationCall += _mappedData.GetValidation(item.Key);
                        switch (item.Value)
                        {
                        case "True":
                            validationValues.Add(item.Key, "01000000");
                            break;

                        case "False":
                            validationValues.Add(item.Key, "00000000");
                            break;

                        default:
                            throw new Exception($@"Unhandled {item.Key} setting detected");
                        }
                        validationCall += @",";
                        break;

                    case "SaveRecoverFlags":
                        jsonString     += _mappedData.keyMapping[item.Key][item.Value];
                        validationCall += _mappedData.GetValidation(item.Key);
                        switch (item.Value)
                        {
                        case "None":
                            validationValues.Add(item.Key, "0000");
                            break;

                        case "Save":
                            validationValues.Add(item.Key, "0100");
                            break;

                        case "Recover":
                            validationValues.Add(item.Key, "0001");
                            break;

                        case "SaveRecover":
                            validationValues.Add(item.Key, "0101");
                            break;

                        default:
                            throw new Exception($@"Unhandled {item.Key} setting detected");
                        }
                        validationCall += @",";
                        break;

                    case "Language":
                        jsonString     += _mappedData.keyMapping[item.Key][item.Value];
                        validationCall += _mappedData.GetValidation(item.Key);
                        switch (item.Value)
                        {
                        case "English":
                            validationValues.Add(item.Key, "09040000");
                            break;

                        case "Korean":
                            validationValues.Add(item.Key, "12040000");
                            break;

                        default:
                            throw new Exception($@"Unhandled {item.Key} setting detected");
                        }
                        validationCall += @",";
                        break;

                    case "SuppressUsed":
                        jsonString     += _mappedData.keyMapping[item.Key][item.Value];
                        validationCall += _mappedData.GetValidation(item.Key);
                        switch (item.Value)
                        {
                        case "True":
                            validationValues.Add(item.Key, "01");
                            break;

                        case "False":
                            validationValues.Add(item.Key, "00");
                            break;

                        default:
                            throw new Exception($@"Unhandled {item.Key} setting detected");
                        }
                        validationCall += @",";
                        break;

                    case "ExecutionMode":
                        jsonString     += _mappedData.keyMapping[item.Key][item.Value];
                        validationCall += _mappedData.GetValidation(item.Key);
                        validationValues.Add(item.Key, item.Value);
                        validationCall += @",";
                        break;

                    case "PartialClean":
                        jsonString += _mappedData.GetPartialClean();
                        //validationCall += _mappedData.GetValidation(item.Key);
                        validationValues.Add(item.Key, "True");
                        break;

                    default:
                        continue;
                    }
                    jsonString += @",";
                }
            }
            jsonString      = jsonString.Remove(jsonString.Length - 1);
            validationCall  = validationCall.Remove(validationCall.Length - 1);
            validationCall += @"]}";

            if (jsonString.Contains("ModelNumber") || jsonString.Contains("SerialNumber"))
            {
                jsonString += @"], ""username"":""admin"", ""password"": " + $@"""{device.AdminPassword}""" + "}";
            }
            else
            {
                jsonString += @",[""845E3285-C67C-4f4b-9AA4-0AE91BD35089"",""LLDataStoreBootAction"",""hex"", ""01000000""],[""845E3285-C67C-4f4b-9AA4-0AE91BD35089"",""PMDataStoreBootAction"",""hex"", ""01000000""]], ""username"":""admin"", ""password"": " + $@"""{device.AdminPassword}""" + "}";
            }

            return(jsonString);
        }
        /// <summary>
        /// Retrieves <see cref="AssetInfo" /> for all assets in the inventory.
        /// </summary>
        /// <returns><see cref="AssetInfo" /> for all assets in the inventory.</returns>
        public AssetInfoCollection GetAssets()
        {
            List <AssetInfo> assets = new List <AssetInfo>();

            DatabaseQuery(Resources.SelectPrinters, record =>
            {
                PrintDeviceInfoInternal deviceInfo = new PrintDeviceInfoInternal
                                                     (
                    (string)record["AssetId"],
                    (AssetAttributes)record["Attributes"],
                    record["PrinterType"] as string,
                    record["Address"] as string,
                    record["Address2"] as string,
                    record["Password"] as string,
                    record["Product"] as string,
                    (int)record["PortNumber"],
                    (bool)record["SnmpEnabled"]
                                                     );

                deviceInfo.Description  = $"{deviceInfo.ProductName} ({(string)record["Model"]}) at {deviceInfo.Address}";
                deviceInfo.ModelName    = record["ModelName"] as string;
                deviceInfo.ModelNumber  = record["ModelNumber"] as string;
                deviceInfo.SerialNumber = record["SerialNumber"] as string;

                assets.Add(deviceInfo);
            });

            DatabaseQuery(Resources.SelectSimulators, record =>
            {
                DeviceSimulatorInfo deviceSimulatorInfo = new DeviceSimulatorInfo
                                                          (
                    (string)record["AssetId"],
                    (AssetAttributes)record["Attributes"],
                    "DeviceSimulator",
                    record["Address"] as string,
                    record["Password"] as string,
                    record["Product"] as string,
                    record["SimulatorType"] as string
                                                          );

                deviceSimulatorInfo.Description = $"{deviceSimulatorInfo.SimulatorType} device simulator at {deviceSimulatorInfo.Address}";
                assets.Add(deviceSimulatorInfo);
            });

            DatabaseQuery(Resources.SelectVirtualPrinters, record =>
            {
                VirtualPrinterInfo virtualPrinterInfo = new VirtualPrinterInfo
                                                        (
                    (string)record["AssetId"],
                    (AssetAttributes)record["Attributes"],
                    "VirtualPrinter",
                    record["Address"] as string,
                    9100,
                    false
                                                        );

                virtualPrinterInfo.Description = $"Virtual printer at {virtualPrinterInfo.Address}";
                assets.Add(virtualPrinterInfo);
            });

            DatabaseQuery(Resources.SelectMobileDevices, record =>
            {
                MobileDeviceInfo mobileDeviceInfo = new MobileDeviceInfo
                                                    (
                    (string)record["AssetId"],
                    (AssetAttributes)record["Attributes"],
                    "MobileDevice",
                    record["MobileEquipmentId"] as string,
                    EnumUtil.Parse <MobileDeviceType>(record["MobileDeviceType"] as string, true)
                                                    );

                mobileDeviceInfo.Description = record["Description"] as string;
                assets.Add(mobileDeviceInfo);
            });

            return(new AssetInfoCollection(assets));
        }
        //Updating status during the parallel for each will lock the UI thread
        private bool UpdateDevice(IDeviceInfo device, LowLevelConfigActivityData data)
        {
            PrintDeviceInfoInternal printDevice = device as PrintDeviceInfoInternal;
            string validationCall = string.Empty;
            Dictionary <string, string> validationValues = new Dictionary <string, string>();


            var json = CreateJson(printDevice, data, ref validationCall, ref validationValues);

            if (json == string.Empty)// || !string.IsNullOrEmpty(data.FimBundle))
            {
                return(true);
            }
            ExecutionServices.SystemTrace.LogDebug(json);


            try
            {
                string callLocation = @"/jedi/nvpconfig";
                string jobId        = POST(_webServiceURL, callLocation, json);

                string status = GET(_webServiceURL, callLocation, jobId);
                //UpdateStatus($"Service Call Successful on device {device.Address}, response: {status}");
                DateTime startTime = DateTime.Now;


                while (status.ToUpper().Contains("PENDING") && startTime + TimeSpan.FromMinutes(15) > DateTime.Now)
                {
                    Thread.Sleep(TimeSpan.FromSeconds(10));
                    status = GET(_webServiceURL, callLocation, jobId);
                }

                if (!status.ToUpper().Contains("SUCCESS"))
                {
                    ExecutionServices.SystemTrace.LogDebug($"Device: {device.AssetId} failed to update NVRAM: Issue{status}");
                    if (status.ToUpper().Contains("PENDING"))
                    {
                        throw new Exception($"Device Unresponsive Exception, please check on device {device.AssetId}");
                    }
                    return(false);
                }
            }
            catch
            {
                throw;
            }


            //Validate here
            if (validationValues.ContainsKey("PartialClean"))
            {
                //We can't validate partial cleans.
                return(true);
            }
            else
            {
                //Otherwise send the nvram call to get the values of the current requested changes.
                string   endurl    = @"/jedi/nvpget";
                string   id        = POST(_webServiceURL, endurl, validationCall);
                string   temp      = GET(_webServiceURL, endurl, id);
                DateTime startTime = DateTime.Now;
                try
                {
                    while (temp.Contains("PENDING") && startTime + TimeSpan.FromMinutes(15) > DateTime.Now)
                    {
                        temp = GET(_webServiceURL, endurl, id);
                        Thread.Sleep(2000);
                        Console.WriteLine(temp);
                    }

                    //JavaScriptSerializer javascriptSerializer = new JavaScriptSerializer();
                    //temp = temp.Substring(1, temp.Length - 2);
                    var items = JsonConvert.DeserializeObject <List <NVRamPackageData> >(temp);

                    foreach (var item in items)
                    {
                        switch (item.Name)
                        {
                        case "SerialNumber":
                        case "ModelNumber":
                        case "ExecutionMode":
                        case "CRDefSleep":
                            byte[] hexval    = FromHex(item.HexValue);
                            string stringRep = Encoding.ASCII.GetString(hexval);

                            if (stringRep == validationValues[item.Name])
                            {
                                continue;
                            }
                            else
                            {
                                return(false);
                            }

                        case "JDIMfgReset":
                        case "SaveRecoverFlags":
                        case "Language":
                        case "RebootCrashMode":
                        case "SuppressUsed":
                            if (item.HexValue == validationValues[item.Name])
                            {
                                continue;
                            }
                            else
                            {
                                return(false);
                            }


                        //break;
                        //case "PartialClean":

                        //    break;
                        default:
                            continue;
                        }
                    }
                }
                catch (Exception ex)
                {
                    ExecutionServices.SystemTrace.LogDebug(ex);
                    throw;
                }

                return(true);
            }
        }