//DateTime? lastStatusUpdate = null;

        /*private void updateStatus(string msg, bool forceUpdate)
         * {
         *  //update status every second so we don't flood the UI with more updates than it can handle
         *  if (forceUpdate || !lastStatusUpdate.HasValue || lastStatusUpdate.Value.AddSeconds(1) < DateTime.Now)
         *  {
         *      if (OnProgressUpdate != null)
         *      {
         *          OnProgressUpdate(msg);
         *      }
         *      lastStatusUpdate = DateTime.Now;
         *  }
         * }*/

        private bool processRow(CSVRow row, CSVFileParser parser)
        {
            try
            {
                using (var uow = UnitOfWorkFactory.CreateUnitOfWork())
                {
                    string baleNumber = row.GetColumnValue(baleColIndex);
                    var    bale       = uow.BalesRepository.FindSingle(x => x.PbiNumber.EndsWith(baleNumber));

                    if (bale != null)
                    {
                        bale.Classing_NetWeight = row.GetDecimalColumnValueNullabe(netWtColIndex);
                        bale.Classing_Pk        = row.GetIntColumnValueNullabe(pkColIndex);
                        bale.Classing_Gr        = row.GetIntColumnValueNullabe(grColIndex);
                        bale.Classing_Lf        = row.GetIntColumnValueNullabe(lfColIndex);
                        bale.Classing_St        = row.GetIntColumnValueNullabe(stColIndex);
                        bale.Classing_Mic       = row.GetDecimalColumnValueNullabe(micColIndex);
                        bale.Classing_Ex        = row.GetIntColumnValueNullabe(exColIndex);
                        bale.Classing_Rm        = row.GetIntColumnValueNullabe(rmColIndex);
                        bale.Classing_Str       = row.GetDecimalColumnValueNullabe(strColIndex);
                        bale.Classing_CGr       = row.GetColumnValue(cgrColIndex);
                        bale.Classing_Rd        = row.GetDecimalColumnValueNullabe(rdColIndex);
                        bale.Classing_Plusb     = row.GetDecimalColumnValueNullabe(plusbColIndex);
                        bale.Classing_Tr        = row.GetIntColumnValueNullabe(trColIndex);
                        bale.Classing_Unif      = row.GetDecimalColumnValueNullabe(unifColIndex);
                        bale.Classing_Len       = row.GetIntColumnValueNullabe(lenColIndex);
                        bale.Classing_Value     = row.GetDecimalColumnValueNullabe(valueColIndex);
                        uow.BalesRepository.Save(bale);
                        uow.SaveChanges();
                    }
                }

                return(true);
            }
            catch (Exception exc)
            {
                Logging.Logger.Log(exc);
                return(false);
            }
        }
        public int processFile(System.IO.FileInfo fileInfo)
        {
            int errorCount = 0;

            try
            {
                int  readTries   = 0;
                bool canReadFile = false;

                while (readTries < 20 && !canReadFile)
                {
                    if (!FileHelper.CanReadFile(fileInfo))
                    {
                        canReadFile = false;
                        System.Threading.Thread.Sleep(500);  //sleep to see if file lock is released
                    }
                    else
                    {
                        canReadFile = true;
                    }
                    readTries++;
                }

                if (!canReadFile)
                {
                    Logging.Logger.Log("ERROR", "Unable to process file " + fileInfo.FullName + ". File is in use by another process");
                    errorCount++;
                    return(errorCount);
                }
                else
                {
                    Logging.Logger.Log("INFO", "Importing file " + fileInfo.FullName + ".");
                }

                var parser = new CSVFileParser(fileInfo.FullName);

                if (parser.LineCount > 1 && canReadFile)
                {
                    int rowCount = 1;

                    //for this row need to get client, farm, field, load number if available, truck, and driver
                    baleColIndex     = parser.Header.FindColumnIndex(new string[] { "Bale" });
                    netWtColIndex    = parser.Header.FindColumnIndex(new string[] { "NetWt", "Net Wt" });
                    loadColIndex     = parser.Header.FindColumnIndex(new string[] { "Load" });
                    producerColIndex = parser.Header.FindColumnIndex(new string[] { "Prod ID" });
                    farmColIndex     = parser.Header.FindColumnIndex(new string[] { "Farm ID" });
                    fieldColIndex    = parser.Header.FindColumnIndex(new string[] { "Field ID" });
                    pkColIndex       = parser.Header.FindColumnIndex(new string[] { "Pk" });
                    grColIndex       = parser.Header.FindColumnIndex(new string[] { "Gr" });
                    lfColIndex       = parser.Header.FindColumnIndex(new string[] { "Lf" });
                    stColIndex       = parser.Header.FindColumnIndex(new string[] { "St" });
                    micColIndex      = parser.Header.FindColumnIndex(new string[] { "Mic" });
                    exColIndex       = parser.Header.FindColumnIndex(new string[] { "Ex" });
                    rmColIndex       = parser.Header.FindColumnIndex(new string[] { "Rm" });
                    strColIndex      = parser.Header.FindColumnIndex(new string[] { "Str" });
                    cgrColIndex      = parser.Header.FindColumnIndex(new string[] { "CGr" });
                    rdColIndex       = parser.Header.FindColumnIndex(new string[] { "Rd" });
                    plusbColIndex    = parser.Header.FindColumnIndex(new string[] { "plusb" });
                    trColIndex       = parser.Header.FindColumnIndex(new string[] { "Tr" });
                    unifColIndex     = parser.Header.FindColumnIndex(new string[] { "Unif" });
                    lenColIndex      = parser.Header.FindColumnIndex(new string[] { "Len" });
                    valueColIndex    = parser.Header.FindColumnIndex(new string[] { "Value" });

                    int totalRows = parser.Rows.Count();
                    foreach (var row in parser.Rows)
                    {
                        //updateStatus(string.Format("Processing file {0} of {1} - row {2} of {3}.", fileNumber, totalFiles, rowCount, totalRows), false);
                        if (!processRow(row, parser))
                        {
                            errorCount++;
                        }
                        rowCount++;
                    }
                }
            }
            catch (Exception exc)
            {
                errorCount++;
                Logging.Logger.Log(exc);
            }

            return(errorCount);
        }
        private bool processRow(CSVRow row, CSVFileParser parser, string filename)
        {
            try
            {
                using (var uow = UnitOfWorkFactory.CreateUnitOfWork())
                {
                    //create a new module document
                    ModuleEntity doc = new ModuleEntity();
                    doc.Name = row.GetColumnValue(serialNumberColIndex);
                    string clientName = row.GetColumnValue(clientColIndex);
                    string farmName   = row.GetColumnValue(farmColIndex);
                    string fieldName  = row.GetColumnValue(fieldColIndex);
                    doc.ImportedLoadNumber = row.GetColumnValue(loadColIndex);
                    doc.Driver             = row.GetColumnValue(driverColIndex);
                    doc.TruckID            = row.GetColumnValue(truckColIndex);
                    doc.Latitude           = row.GetDoubleColumnValue(latitudeColIndex);
                    doc.Longitude          = row.GetDoubleColumnValue(longitudeColIndex);
                    doc.Notes            = row.GetColumnValue(commentsColIndex);
                    doc.GinTagLoadNumber = row.GetColumnValue(ginTicketColIndex).TrimStart('0');
                    doc.ModuleId         = row.GetColumnValue(moduleIdColIndex);

                    doc.HIDDiameter        = row.GetDecimalColumnValueNullabe(hidDiameterIndex);
                    doc.HIDFieldArea       = row.GetDecimalColumnValueNullabe(hidFieldArea);
                    doc.HIDIncrementalArea = row.GetDecimalColumnValueNullabe(hidIncrementalAreaIndex);
                    doc.HIDModuleWeight    = row.GetDecimalColumnValueNullabe(hidModuleWeightIndex);
                    doc.HIDMoisture        = row.GetDecimalColumnValueNullabe(hidMoistureIndex);
                    doc.HIDOperator        = row.GetColumnValue(hidOperatorIndex);
                    doc.HIDProducerID      = row.GetColumnValue(hidProducerIDIndex);
                    doc.HIDGMTDate         = row.GetColumnValue(hidGMTDateIndex);
                    doc.HIDGMTTime         = row.GetColumnValue(hidGMTTimeIndex);

                    DateTime ts = DateTime.Now;

                    if (DateTime.TryParse(doc.HIDGMTDate + " " + doc.HIDGMTTime, out ts))
                    {
                        doc.HIDTimestamp = ts;
                    }
                    else
                    {
                        doc.HIDTimestamp = null;
                    }

                    doc.HIDSeasonTotal = row.GetIntColumnValueNullabe(hidSeasonTotalIndex);
                    doc.HIDFieldTotal  = row.GetIntColumnValueNullabe(hidFieldTotalIndex);
                    doc.HIDVariety     = row.GetColumnValue(hidVarietyIndex);

                    doc.HIDLat        = row.GetDoubleColumnValue(latitudeColIndex);
                    doc.HIDLong       = row.GetDoubleColumnValue(longitudeColIndex);
                    doc.HIDDropLat    = row.GetDoubleColumnValue(hidDropLat);
                    doc.HIDDropLong   = row.GetDoubleColumnValue(hidDropLong);
                    doc.HIDWrapLat    = row.GetDoubleColumnValue(hidWrapLat);
                    doc.HIDWrapLong   = row.GetDoubleColumnValue(hidWrapLon);
                    doc.HIDGinID      = row.GetColumnValue(hidGinID);
                    doc.HIDMachinePIN = row.GetColumnValue(hidMachinePIN);

                    doc.GinTagLoadNumber = row.GetColumnValue(ginTicketColIndex).TrimStart('0');

                    doc.Name = doc.Name.Trim();

                    string clientID = row.GetColumnValue(clientIDColIndex);
                    string farmID   = row.GetColumnValue(farmIDColIndex);
                    string fieldID  = row.GetColumnValue(fieldIDColIndex);

                    ModuleEventType eventType = ModuleEventType.IMPORTED_FROM_FILE;
                    DateTime        created   = DateTime.Now;
                    if (filename.ToLower().Contains("transmission"))
                    {
                        eventType = ModuleEventType.IMPORTED_FROM_RFID_MODULESCAN;
                        if (!DateTime.TryParse(row.GetColumnValue(timestampIndex), out created))
                        {
                            if (doc.HIDTimestamp.HasValue)
                            {
                                created = doc.HIDTimestamp.Value;
                            }
                        }
                        else
                        {
                            created = created.ToUniversalTime();
                        }
                    }
                    else
                    {
                        eventType = ModuleEventType.IMPORTED_FROM_HID;
                        if (doc.HIDTimestamp.HasValue)
                        {
                            created = doc.HIDTimestamp.Value;
                        }
                    }

                    ModuleHistoryEntity historyItem = new ModuleHistoryEntity
                    {
                        Id               = Guid.NewGuid().ToString(),
                        Created          = created,
                        Driver           = doc.Driver,
                        TruckID          = doc.TruckID,
                        BridgeId         = string.Empty,
                        BridgeLoadNumber = null,
                        GinTagLoadNumber = doc.GinTagLoadNumber,
                        Latitude         = doc.Latitude,
                        Longitude        = doc.Longitude,
                        ModuleEventType  = eventType
                    };
                    doc.ModuleHistory.Add(historyItem);

                    //determine if serial number exists if so skip
                    bool canSave   = !string.IsNullOrWhiteSpace(doc.Name) && !existingSerialNumbers.ContainsKey(doc.Name);
                    bool canUpdate = !string.IsNullOrWhiteSpace(doc.Name) && existingSerialNumbers.ContainsKey(doc.Name);

                    if (canSave)
                    {
                        existingSerialNumbers.Add(doc.Name, true);
                        ClientEntity existingClient = uow.ClientRepository.FindSingle(c => c.Name == clientName.Trim(), "Farms.Fields");
                        FarmEntity   existingFarm   = null;
                        FieldEntity  existingField  = null;

                        if (existingClient == null)
                        {
                            //add client/farm/field and module
                            if (!string.IsNullOrWhiteSpace(clientName))
                            {
                                existingClient       = new ClientEntity();
                                existingClient.Farms = new List <FarmEntity>();
                                existingClient.Name  = clientName.Trim();
                                uow.ClientRepository.CreateWithID(existingClient, clientID);
                            }
                            else
                            {
                                Logging.Logger.Log("INFO", string.Format("Cannot save client for new module with SN {0} - name is empty.", doc.Name));
                                return(false);
                            }
                        }

                        existingFarm = uow.FarmRepository.FindSingle(f => f.Name == farmName.Trim() && f.ClientId == existingClient.Id);

                        if (existingFarm == null)
                        {
                            var canSaveFarm = !(string.IsNullOrWhiteSpace(farmName));

                            if (!canSaveFarm)
                            {
                                Logging.Logger.Log("INFO", string.Format("Cannot save farm {0} for new module with SN {1} - name empty or duplicate farm already exists for another client.", doc.FarmName, doc.Name));
                                return(false);
                            }
                            else
                            {
                                //add farm/field to client
                                existingFarm          = new FarmEntity();
                                existingFarm.Fields   = new List <FieldEntity>();
                                existingFarm.Name     = farmName.Trim();
                                existingFarm.ClientId = existingClient.Id;
                                uow.FarmRepository.CreateWithID(existingFarm, farmID);
                            }
                        }

                        existingField = uow.FieldRepository.FindSingle(f => f.Name.Trim() == fieldName.Trim() && f.FarmId == existingFarm.Id);

                        if (existingField == null)
                        {
                            if (!string.IsNullOrWhiteSpace(fieldName))
                            {
                                existingField           = new FieldEntity();
                                existingField.Name      = fieldName.Trim();
                                existingField.Latitude  = 0.00;
                                existingField.Longitude = 0.00;
                                existingField.FarmId    = existingFarm.Id;
                                uow.FieldRepository.CreateWithID(existingField, fieldID);
                            }
                            else
                            {
                                Logging.Logger.Log("INFO", string.Format("Cannot save field for new module with SN {0} - field name empty.", doc.Name));
                                return(false);
                            }
                        }

                        if (uow.SettingsRepository.CoordsAtFeeder(doc.Latitude, doc.Longitude))
                        {
                            doc.ModuleStatus = ModuleStatus.ON_FEEDER;
                        }
                        else if (uow.SettingsRepository.CoordsOnGinYard(doc.Latitude, doc.Longitude))
                        {
                            doc.ModuleStatus = ModuleStatus.AT_GIN;
                        }
                        else
                        {
                            doc.ModuleStatus = ModuleStatus.IN_FIELD; //change status back to field
                        }

                        historyItem.ModuleStatus = doc.ModuleStatus;
                        doc.FieldId       = existingField.Id;
                        doc.SyncedToCloud = false; // Added 5/23
                        uow.ModuleRepository.Save(doc);
                        uow.SaveChanges();
                        return(true);
                    }
                    else if (canUpdate)
                    {
                        var affectedModule = uow.ModuleRepository.FindSingle(x => x.Name == doc.Name, "ModuleHistory");
                        affectedModule.Latitude  = doc.Latitude;
                        affectedModule.Longitude = doc.Longitude;
                        if (uow.SettingsRepository.CoordsAtFeeder(doc.Latitude, doc.Longitude))
                        {
                            affectedModule.ModuleStatus = ModuleStatus.ON_FEEDER;
                        }
                        else if (uow.SettingsRepository.CoordsOnGinYard(doc.Latitude, doc.Longitude))
                        {
                            affectedModule.ModuleStatus = ModuleStatus.AT_GIN;
                        }
                        else
                        {
                            affectedModule.ModuleStatus = ModuleStatus.IN_FIELD; //change status back to field
                        }
                        if (!string.IsNullOrWhiteSpace(doc.ImportedLoadNumber))
                        {
                            affectedModule.ImportedLoadNumber = doc.ImportedLoadNumber;
                        }

                        historyItem.ModuleStatus = affectedModule.ModuleStatus;
                        affectedModule.ModuleHistory.Add(historyItem);
                        affectedModule.SyncedToCloud = false;
                        uow.ModuleRepository.Save(affectedModule);
                        uow.SaveChanges();
                        return(true);
                    }
                    else
                    {
                        Logging.Logger.Log("INFO", "Cannot save empty or duplicate serial number: " + doc.Name);
                        return(false);
                    }
                }
            }
            catch (Exception exc)
            {
                Logging.Logger.Log(exc);
                return(false);
            }
        }
        private async Task <int> processFile(FileInfo fileInfo, int fileNumber, int totalFiles)
        {
            int errorCount = 0;

            try
            {
                int  readTries   = 0;
                bool canReadFile = false;

                while (readTries < 20 && !canReadFile)
                {
                    if (!CanReadFile(fileInfo))
                    {
                        canReadFile = false;
                        System.Threading.Thread.Sleep(500);  //sleep to see if file lock is released
                    }
                    else
                    {
                        canReadFile = true;
                    }
                    readTries++;
                }

                if (!canReadFile)
                {
                    Logging.Logger.Log("ERROR", "Unable to process file " + fileInfo.FullName + ". File is in use by another process");
                    errorCount++;
                    return(errorCount);
                }
                else
                {
                    Logging.Logger.Log("INFO", "Importing file " + fileInfo.FullName + ".");
                }

                var parser = new CSVFileParser(fileInfo.FullName);

                if (parser.LineCount > 1 && canReadFile)
                {
                    int rowCount = 1;

                    //for this row need to get client, farm, field, load number if available, truck, and driver
                    clientColIndex       = parser.Header.FindColumnIndex(new string[] { "Client", "Grower" });
                    farmColIndex         = parser.Header.FindColumnIndex(new string[] { "Farm" });
                    fieldColIndex        = parser.Header.FindColumnIndex(new string[] { "Field" });
                    loadColIndex         = parser.Header.FindColumnIndex(new string[] { "Load" });
                    serialNumberColIndex = parser.Header.FindColumnIndex(new string[] { "Module SN", "SerialNumber", "Serial Number" });
                    driverColIndex       = parser.Header.FindColumnIndex(new string[] { "Driver" });
                    truckColIndex        = parser.Header.FindColumnIndex(new string[] { "Truck" });
                    latitudeColIndex     = parser.Header.FindColumnIndex(new string[] { "Lat", "Latitude" });
                    longitudeColIndex    = parser.Header.FindColumnIndex(new string[] { "Lon", "Longitude" });
                    commentsColIndex     = parser.Header.FindColumnIndex(new string[] { "Comment", "Comments", "Note", "Notes" });
                    ginTicketColIndex    = parser.Header.FindColumnIndex(new string[] { "GinTicketLoadNumber", "GinTagLoadNumber" });
                    moduleIdColIndex     = parser.Header.FindColumnIndex(new string[] { "ModuleID", "Module ID" });
                    clientIDColIndex     = parser.Header.FindColumnIndex(new string[] { "GrowerID", "ClientID" });
                    farmIDColIndex       = parser.Header.FindColumnIndex(new string[] { "FarmID" });

                    hidDiameterIndex        = parser.Header.FindColumnIndex(new string[] { "Diameter (cm)" });
                    hidFieldArea            = parser.Header.FindColumnIndex(new string[] { "Field Area (Sq m)" });
                    hidIncrementalAreaIndex = parser.Header.FindColumnIndex(new string[] { "Incremental Area (Sq m)" });
                    hidModuleWeightIndex    = parser.Header.FindColumnIndex(new string[] { "Weight (kg)" });
                    hidMoistureIndex        = parser.Header.FindColumnIndex(new string[] { "Moisture %", "Moisture", "Moisture (%)" });
                    hidOperatorIndex        = parser.Header.FindColumnIndex(new string[] { "Operator" });
                    hidProducerIDIndex      = parser.Header.FindColumnIndex(new string[] { "Producer ID" });
                    hidVarietyIndex         = parser.Header.FindColumnIndex(new string[] { "Variety" });
                    hidSeasonTotalIndex     = parser.Header.FindColumnIndex(new string[] { "Season Total" });
                    hidGMTDateIndex         = parser.Header.FindColumnIndex(new string[] { "GMT Date" });
                    hidGMTTimeIndex         = parser.Header.FindColumnIndex(new string[] { "GMT Time" });
                    timestampIndex          = parser.Header.FindColumnIndex(new string[] { "Timestamp" });
                    hidFieldTotalIndex      = parser.Header.FindColumnIndex(new string[] { "Field Total" });
                    //ginTicketColIndex = parser.Header.FindColumnIndex(new string[] { "GinTicketLoadNumber", "GinTagLoadNumber", "Gin Tag Load Number", "Gin Ticket Load Number" });

                    hidDropLat    = parser.Header.FindColumnIndex(new string[] { "Drop Lat", "Drop Latitude" });
                    hidDropLong   = parser.Header.FindColumnIndex(new string[] { "Drop Lon", "Drop Longitude" });
                    hidWrapLat    = parser.Header.FindColumnIndex(new string[] { "Wrap Lat", "Wrap Latitude" });
                    hidWrapLon    = parser.Header.FindColumnIndex(new string[] { "Wrap Lon", "Wrap Longitude" });
                    hidGinID      = parser.Header.FindColumnIndex(new string[] { "Gin ID", "Gin" });
                    hidMachinePIN = parser.Header.FindColumnIndex(new string[] { "Machine PIN", "Machine VIN" });

                    fieldIDColIndex = parser.Header.FindColumnIndex(new string[] { "FieldID" });
                    existingSerialNumbers.Clear();

                    using (var uow = UnitOfWorkFactory.CreateUnitOfWork())
                    {
                        foreach (var sn in uow.ModuleRepository.GetAllSerialNumbers())
                        {
                            existingSerialNumbers.Add(sn, true);
                        }
                    }

                    int totalRows = parser.Rows.Count();
                    foreach (var row in parser.Rows)
                    {
                        updateStatus(string.Format("Processing file {0} of {1} - row {2} of {3}.", fileNumber, totalFiles, rowCount, totalRows), false);
                        if (!processRow(row, parser, fileInfo.FullName))
                        {
                            errorCount++;
                        }
                        rowCount++;
                    }
                }
            }
            catch (Exception exc)
            {
                errorCount++;
                Logging.Logger.Log(exc);
            }

            return(errorCount);
        }