/// <summary>
        /// Save all sections & works to database (direct)
        /// </summary>
        /// <param name="workId">workId</param>
        /// <param name="projectId">projectId</param>
        /// <param name="sectionAssetId">sectionAssetId</param>
        /// <param name="countryId">countryId</param>
        /// <param name="provinceId">provinceId</param>
        /// <param name="countyId">countyId</param>
        /// <param name="cityId">cityId</param>
        /// <param name="length">length</param>
        /// <param name="companyId">companyId</param>
        /// <param name="isNewMeasuredFromDsmh">isNewMeasuredFromDsmh</param>
        /// <param name="prepDataRoboticPrep">prepDataRoboticPrep</param>
        /// <param name="prepDataRoboticPrepCompleted">prepDataRoboticPrepCompleted</param>
        public void Save(int workId, int projectId, int sectionAssetId, Int64 countryId, Int64? provinceId, Int64? countyId, Int64? cityId, string length, int companyId, bool isNewMeasuredFromDsmh, bool prepDataRoboticPrep, DateTime? prepDataRoboticPrepCompleted)
        {
            // Update Laterals
            RehabAssessmentLateralDetailsGateway rehabAssessmentLateralDetailsGateway = new RehabAssessmentLateralDetailsGateway(Data);

            if (rehabAssessmentLateralDetailsGateway.Table.Rows.Count > 0)
            {
                // Get WorkId
                if (workId == 0)
                {
                    WorkFullLengthLining workFullLengthLining = new WorkFullLengthLining(null);
                    workId = workFullLengthLining.InsertDirectEmptyWorks(projectId, sectionAssetId, null, "", null, null, null, null, null, null, null, false, false, false, false, false, false, false, companyId, false, "", "");
                }

                foreach (RehabAssessmentTDS.LateralDetailsRow row in (RehabAssessmentTDS.LateralDetailsDataTable)Table)
                {
                    int lateral = row.Lateral;

                    ProjectGateway projectGateway = new ProjectGateway();
                    projectGateway.LoadByProjectId(projectId);
                    int clientId = projectGateway.GetClientID(projectId);

                    // ... Insert lateral
                    if ((!row.InDatabase) && (!row.Deleted))
                    {
                        string videoDistance = rehabAssessmentLateralDetailsGateway.GetVideoDistance(lateral);
                        string clockPosition = rehabAssessmentLateralDetailsGateway.GetClockPosition(lateral);
                        string distanceToCentre = rehabAssessmentLateralDetailsGateway.GetDistanceToCentre(lateral);
                        string timeOpened = rehabAssessmentLateralDetailsGateway.GetTimeOpened(lateral);
                        string reverseSetup = rehabAssessmentLateralDetailsGateway.GetReverseSetup(lateral);
                        DateTime? reinstate = rehabAssessmentLateralDetailsGateway.GetReinstate(lateral);
                        string comments = rehabAssessmentLateralDetailsGateway.GetComments(lateral);
                        string clientLateralId = rehabAssessmentLateralDetailsGateway.GetClientLateralId(lateral);
                        string clientInspectionNo = rehabAssessmentLateralDetailsGateway.GetClientInspectionNo(lateral);
                        DateTime? v1Inspection = rehabAssessmentLateralDetailsGateway.GetV1Inspection(lateral);
                        bool requiredRoboticPrep = rehabAssessmentLateralDetailsGateway.GetRequiresRoboticPrep(lateral);
                        DateTime? requiredRoboticPrepDate = rehabAssessmentLateralDetailsGateway.GetRequiresRoboticPrepDate(lateral);
                        bool holdClientIssue = rehabAssessmentLateralDetailsGateway.GetHoldClientIssue(lateral);
                        bool holdLFSIssue = rehabAssessmentLateralDetailsGateway.GetHoldLFSIssue(lateral);
                        bool lineLateral = rehabAssessmentLateralDetailsGateway.GetLineLateral(lateral);
                        string flange = rehabAssessmentLateralDetailsGateway.GetFlange(lateral);
                        bool dyeTestReq = rehabAssessmentLateralDetailsGateway.GetDyeTestReq(lateral);
                        DateTime? dyeTestComplete = null; if (rehabAssessmentLateralDetailsGateway.GetDyeTestComplete(lateral).HasValue) dyeTestComplete = rehabAssessmentLateralDetailsGateway.GetDyeTestComplete(lateral);
                        string contractYear = rehabAssessmentLateralDetailsGateway.GetContractYear(lateral);

                        // ... ... Insert asset
                        int lateral_assetId = SaveLateral(row, projectId, sectionAssetId, countryId, provinceId, countyId, cityId, companyId, isNewMeasuredFromDsmh);

                        // ... ... Insert lateral to FulllengthLining
                        InsertFLLLateral(workId, lateral_assetId, videoDistance, clockPosition, distanceToCentre, timeOpened, reverseSetup, reinstate, comments, false, companyId, clientInspectionNo, v1Inspection, requiredRoboticPrep, requiredRoboticPrepDate, holdClientIssue, holdLFSIssue, lineLateral, dyeTestReq, dyeTestComplete, contractYear);

                        // ... ... If lateral will be in Junction Lining
                        if ((row.LineLateral) && (!row.InJlDatabase))
                        {
                            if (((!prepDataRoboticPrep) && (!prepDataRoboticPrepCompleted.HasValue)) || ((prepDataRoboticPrep) && (prepDataRoboticPrepCompleted.HasValue)))
                            {
                                // ... ... Load work id
                                int sectionWorkId = 0;
                                WorkJunctionLiningSection workJunctionLiningSection = new WorkJunctionLiningSection(null);
                                sectionWorkId = workJunctionLiningSection.InsertDirect(projectId, sectionAssetId, null, 0, 0, false, "No", 0, 0, false, companyId, "", "", "", "", false, "", 0);

                                WorkJunctionLiningLateralGateway workJunctionLiningLateralGateway = new WorkJunctionLiningLateralGateway();
                                WorkJunctionLiningLateral workJunctionLiningLateral = new WorkJunctionLiningLateral(workJunctionLiningLateralGateway.Data);
                                workJunctionLiningLateral.InsertDirect(projectId, lateral_assetId, sectionWorkId, null, null, null, null, null, null, null, null, null, "", null, null, null, 0, null, null, null, 0, v1Inspection, true, false, "", false, null, null, false, companyId, "", "", "", false, null, "", flange, "", "", false, null, false, null, false, holdClientIssue, null, holdLFSIssue, null, requiredRoboticPrep, requiredRoboticPrepDate, "", "", dyeTestReq, dyeTestComplete, contractYear);
                            }
                        }

                        // ... Insert material for M1 lateral
                        try
                        {
                            string material = rehabAssessmentLateralDetailsGateway.GetMaterialType(lateral);
                            if (material != "")
                            {
                                InsertMaterial(lateral_assetId, material, companyId);
                            }
                        }
                        catch { }

                        //... Insert client lateral id
                        try
                        {
                            if (clientLateralId.Trim() != "")
                            {
                                LfsAssetSewerLateralClient lfsAssetSewerLateralClient = new LfsAssetSewerLateralClient(null);
                                lfsAssetSewerLateralClient.InsertDirect(lateral_assetId, clientId, clientLateralId, false, companyId);
                            }
                        }
                        catch { }
                    }

                    // ... Edit laterals
                    if ((row.InDatabase) && (!row.Deleted))
                    {
                        // original values
                        string originalVideoDistance = rehabAssessmentLateralDetailsGateway.GetVideoDistanceOriginal(lateral);
                        string originalClockPosition = rehabAssessmentLateralDetailsGateway.GetClockPositionOriginal(lateral);
                        string originalDistanceToCentre = rehabAssessmentLateralDetailsGateway.GetDistanceToCentreOriginal(lateral);
                        string originalTimeOpened = rehabAssessmentLateralDetailsGateway.GetTimeOpenedOriginal(lateral);
                        string originalReverseSetup = rehabAssessmentLateralDetailsGateway.GetReverseSetupOriginal(lateral);
                        DateTime? originalReinstate = rehabAssessmentLateralDetailsGateway.GetReinstateOriginal(lateral);
                        string originalComments = rehabAssessmentLateralDetailsGateway.GetCommentsOriginal(lateral);
                        string originalClientLateralId = rehabAssessmentLateralDetailsGateway.GetClientLateralIdOriginal(lateral);
                        string originalClientInspectionNo = rehabAssessmentLateralDetailsGateway.GetClientInspectionNoOriginal(lateral);
                        DateTime? originalV1Inspection = rehabAssessmentLateralDetailsGateway.GetV1InspectionOriginal(lateral);
                        bool originalRequiresRoboticPrep = rehabAssessmentLateralDetailsGateway.GetRequiresRoboticPrepOriginal(lateral);
                        DateTime? originalRequiresRoboticPrepDate = rehabAssessmentLateralDetailsGateway.GetRequiresRoboticPrepDateOriginal(lateral);
                        bool originalHoldClientIssue = rehabAssessmentLateralDetailsGateway.GetHoldClientIssueOriginal(lateral);
                        bool originalHoldLFSIssue = rehabAssessmentLateralDetailsGateway.GetHoldLFSIssueOriginal(lateral);
                        bool originalLineLateral = rehabAssessmentLateralDetailsGateway.GetLineLateralOriginal(lateral);
                        bool originalDyeTestReq = rehabAssessmentLateralDetailsGateway.GetDyeTestReqOriginal(lateral);
                        DateTime? originalDyeTestComplete = null; if (rehabAssessmentLateralDetailsGateway.GetDyeTestCompleteOriginal(lateral).HasValue) originalDyeTestComplete = rehabAssessmentLateralDetailsGateway.GetDyeTestCompleteOriginal(lateral);
                        string originalContractYear = rehabAssessmentLateralDetailsGateway.GetContractYearOriginal(lateral);

                        // new values
                        string newVideoDistance = rehabAssessmentLateralDetailsGateway.GetVideoDistance(lateral);
                        string newClockPosition = rehabAssessmentLateralDetailsGateway.GetClockPosition(lateral);
                        string newDistanceToCentre = rehabAssessmentLateralDetailsGateway.GetDistanceToCentre(lateral);
                        string newTimeOpened = rehabAssessmentLateralDetailsGateway.GetTimeOpened(lateral);
                        string newReverseSetup = rehabAssessmentLateralDetailsGateway.GetReverseSetup(lateral);
                        DateTime? newReinstate = rehabAssessmentLateralDetailsGateway.GetReinstate(lateral);
                        string newComments = rehabAssessmentLateralDetailsGateway.GetComments(lateral);
                        string newClientLateralId = rehabAssessmentLateralDetailsGateway.GetClientLateralId(lateral);
                        string newClientInspectionNo = rehabAssessmentLateralDetailsGateway.GetClientInspectionNo(lateral);
                        DateTime? newV1Inspection = rehabAssessmentLateralDetailsGateway.GetV1Inspection(lateral);
                        bool newRequiresRoboticPrep = rehabAssessmentLateralDetailsGateway.GetRequiresRoboticPrep(lateral);
                        DateTime? newRequiresRoboticPrepDate = rehabAssessmentLateralDetailsGateway.GetRequiresRoboticPrepDate(lateral);
                        bool newHoldClientIssue = rehabAssessmentLateralDetailsGateway.GetHoldClientIssue(lateral);
                        bool newHoldLFSIssue = rehabAssessmentLateralDetailsGateway.GetHoldLFSIssue(lateral);
                        bool newLineLateral = rehabAssessmentLateralDetailsGateway.GetLineLateral(lateral);
                        string newFlange = rehabAssessmentLateralDetailsGateway.GetFlange(lateral);
                        bool newDyeTestReq = rehabAssessmentLateralDetailsGateway.GetDyeTestReq(lateral);
                        DateTime? newDyeTestComplete = null; if (rehabAssessmentLateralDetailsGateway.GetDyeTestComplete(lateral).HasValue) newDyeTestComplete = rehabAssessmentLateralDetailsGateway.GetDyeTestComplete(lateral);
                        string newContractYear = rehabAssessmentLateralDetailsGateway.GetContractYear(lateral);

                        // ... Update laterals
                        int lateral_assetId = SaveLateral(row, projectId, sectionAssetId, countryId, provinceId, countyId, cityId, companyId, isNewMeasuredFromDsmh);
                        UpdateLateral(row, projectId, sectionAssetId, countryId, provinceId, countyId, cityId, length, companyId);

                        // ... Update if lateral is in FulllenghtLining
                        if (!row.InFllDatabase)
                        {
                            WorkFullLengthLiningM1LateralGateway workFullLengthLiningM1LateralGateay = new WorkFullLengthLiningM1LateralGateway();
                            workFullLengthLiningM1LateralGateay.LoadAllByWorkIdLateral(workId, lateral_assetId, companyId);

                            if (workFullLengthLiningM1LateralGateay.Table.Rows.Count == 0)
                            {
                                InsertFLLLateral(workId, lateral_assetId, newVideoDistance, newClockPosition, newDistanceToCentre, newTimeOpened, newReverseSetup, newReinstate, newComments, false, companyId, newClientInspectionNo, newV1Inspection, newRequiresRoboticPrep, newRequiresRoboticPrepDate, newHoldClientIssue, newHoldLFSIssue, newLineLateral, newDyeTestReq, newDyeTestComplete, newContractYear);
                            }
                            else
                            {
                                UpdateFLLLateral(workId, lateral_assetId, originalVideoDistance, originalClockPosition, originalDistanceToCentre, originalTimeOpened, originalReverseSetup, originalReinstate, originalComments, true, companyId, originalClientInspectionNo, originalV1Inspection, originalRequiresRoboticPrep, originalRequiresRoboticPrepDate, originalHoldClientIssue, originalHoldLFSIssue, originalLineLateral, originalDyeTestReq, originalDyeTestComplete, originalContractYear, workId, lateral_assetId, newVideoDistance, newClockPosition, newDistanceToCentre, newTimeOpened, newReverseSetup, newReinstate, newComments, false, companyId, newClientInspectionNo, newV1Inspection, newRequiresRoboticPrep, newRequiresRoboticPrepDate, newHoldClientIssue, newHoldLFSIssue, newLineLateral, newDyeTestReq, newDyeTestComplete, newContractYear);
                            }
                        }
                        else
                        {
                            UpdateFLLLateral(workId, lateral_assetId, originalVideoDistance, originalClockPosition, originalDistanceToCentre, originalTimeOpened, originalReverseSetup, originalReinstate, originalComments, false, companyId, originalClientInspectionNo, originalV1Inspection, originalRequiresRoboticPrep, originalRequiresRoboticPrepDate, originalHoldClientIssue, originalHoldLFSIssue, originalLineLateral, originalDyeTestReq, originalDyeTestComplete, originalContractYear,workId, lateral_assetId, newVideoDistance, newClockPosition, newDistanceToCentre, newTimeOpened, newReverseSetup, newReinstate, newComments, false, companyId, newClientInspectionNo, newV1Inspection, newRequiresRoboticPrep, newRequiresRoboticPrepDate, newHoldClientIssue, newHoldLFSIssue, newLineLateral, newDyeTestReq, newDyeTestComplete, newContractYear);
                        }

                        // ... Update if lateral is in Junction Lining
                        if (row.InJlDatabase)
                        {
                            if (originalLineLateral == newLineLateral)
                            {
                                // ... ... Update jl lateral (clientInspectionNo, v1Inspection, requiredRoboticPrep, requiredRoboticPrepDate, holdClientIssue, holdLFSIssue, flange)
                                UpdateJLLaterals(projectId, lateral_assetId, companyId, newV1Inspection, newClientInspectionNo, newRequiresRoboticPrep, newRequiresRoboticPrepDate, newHoldClientIssue, newHoldLFSIssue, newFlange, newDyeTestReq, newDyeTestComplete, newContractYear);
                            }
                            else
                            {
                                int sectionWorkId = 0;
                                WorkJunctionLiningSection workJunctionLiningSection = new WorkJunctionLiningSection(null);
                                sectionWorkId = workJunctionLiningSection.InsertDirect(projectId, sectionAssetId, null, 0, 0, false, "No", 0, 0, false, companyId, "", "", "", "", false, "", 0);

                                // Delete empty lateral form jl.
                                DeleteJLLaterals(projectId, lateral_assetId, companyId, sectionWorkId);
                            }
                        }
                        else
                        {
                            // ... ... Insert if should be in junction Lining
                            if (row.LineLateral)
                            {
                                if (((!prepDataRoboticPrep) && (!prepDataRoboticPrepCompleted.HasValue)) || ((prepDataRoboticPrep) && (prepDataRoboticPrepCompleted.HasValue)))
                                {
                                    int sectionWorkId = 0;

                                    // Insert to jl laterals
                                    WorkJunctionLiningSection workJunctionLiningSection = new WorkJunctionLiningSection(null);
                                    sectionWorkId = workJunctionLiningSection.InsertDirect(projectId, sectionAssetId, null, 0, 0, false, "No", 0, 0, false, companyId, "", "", "", "", false, "", 0);

                                    WorkJunctionLiningLateralGateway workJunctionLiningLateralGateway = new WorkJunctionLiningLateralGateway();
                                    WorkJunctionLiningLateral workJunctionLiningLateral = new WorkJunctionLiningLateral(workJunctionLiningLateralGateway.Data);
                                    workJunctionLiningLateral.InsertDirect(projectId, lateral_assetId, sectionWorkId, null, null, null, null, null, null, null, null, null, "", null, null, null, 0, null, null, null, 0, newV1Inspection, false, false, "", false, null, null, false, companyId, "", "", "", false, null, newClientInspectionNo, newFlange, "", "", false, null, false, null, false, newHoldClientIssue, null, newHoldLFSIssue, null, newRequiresRoboticPrep, newRequiresRoboticPrepDate, "", "", newDyeTestReq, newDyeTestComplete, newContractYear);
                                }
                            }
                        }

                        string material = rehabAssessmentLateralDetailsGateway.GetMaterialType(lateral);
                        if (material != "")
                        {
                            InsertMaterial(lateral_assetId, material, companyId);
                        }

                        try
                        {
                            LfsAssetSewerLateralClientGateway lfsAssetSewerLateralClientGateway = new LfsAssetSewerLateralClientGateway();
                            lfsAssetSewerLateralClientGateway.LoadAllByAssetIdClientId(lateral_assetId, clientId, companyId);

                            if (lfsAssetSewerLateralClientGateway.Table.Rows.Count == 0)
                            {
                                LfsAssetSewerLateralClient lfsAssetSewerLateralClient = new LfsAssetSewerLateralClient(null);
                                lfsAssetSewerLateralClient.InsertDirect(lateral_assetId, clientId, originalClientLateralId, false, companyId);
                            }
                            else
                            {
                                LfsAssetSewerLateralClient lfsAssetSewerLateralClient = new LfsAssetSewerLateralClient(null);
                                string originalClientLateralId2 = lfsAssetSewerLateralClientGateway.GetClientLateralId(lateral_assetId, clientId);

                                lfsAssetSewerLateralClient.UpdateDirect(lateral_assetId, clientId, originalClientLateralId, false, companyId, lateral_assetId, clientId, newClientLateralId, false, companyId);
                            }
                        }
                        catch
                        { }
                    }

                    // ... Delete laterals
                    if ((row.InDatabase) && (row.Deleted))
                    {
                        DeleteFLLLateral(workId, row.Lateral, companyId, clientId);
                    }
                }
            }
        }