
//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//
// Show content from C# method names
//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//

// Overwritten by <script> tag injected after this file loads (sourced from Varinfo.BrandUrls in DB)
var sBrandUrls = {};





function ShowContentByMethodName(methodname, ...arguments) {

    try {
        // Try to call the function by name
        window[methodname](arguments);
        return true;
    }
    catch (e) {
        // Cannot show this content
        ToastError("Show content", e.name + ": " + e.message);
        return false;
    }

    // Cannot show this content
    return false;
}

function ShowHomeAllViews() { ShowStContent("HOMEALLVIEWS", ""/*ValueString*/, "Home (All Views)"); }
function ShowBillingRatesGridView() { ShowStContent("BILLINGRATESGRID", ""/*ValueString*/, "Billing Rates"); }
function ShowCustomColumnsGridView() { ShowStContent("CUSTOMCOLUMNSGRID", ""/*ValueString*/, "Custom Fields"); }
function ShowPortfoliosGridView() { ShowStContent("PORTFOLIOGRID", ""/*ValueString*/, "Portfolios"); }
function ShowAssemblyLinesGridView() { ShowStContent("ASSYLINEGRID", ""/*ValueString*/, "Assy Lines"); }
function ShowProjectRevenueChartView() { ShowStContent("PROJECTREVENUECHART", ""/*ValueString*/, "Project Revenue"); }
function ShowProjectControlGridView() { ShowStContent("PROJECTCONTROLGRID", ""/*ValueString*/, "Project Control"); }
function ShowAttachmentsGridView() { ShowStContent("ATTACHMENTSGRID", ""/*ValueString*/, "Attachments"); }
function ShowApproveTimesheetsGridView() { ShowStContent("APPROVETIMESHEETS", ""/*ValueString*/, "Approvals"); }
function ShowRoundingGridView() { ShowStContent("ROUNDINGGRID", ""/*ValueString*/, "Rounding"); }
function ShowOvertimeGridView() { ShowStContent("OVERTIMEGRID", ""/*ValueString*/, "Overtime"); }
function ShowEmployeeSchedulesGridView() { ShowStContent("EMPLSCHEDULESGRID", ""/*ValueString*/, "Schedules"); }
function ShowRoleGridView() { ShowStContent("ROLEGRID", ""/*ValueString*/, "Roles"); }
function ShowTimeOffReasonsGridView() { ShowStContent("TIMEOFFREASONGRID", ""/*ValueString*/, "Time Off Reasons"); }
function ShowTimeOffPoliciesGridView() { ShowStContent("TIMEOFFPOLICYGRID", ""/*ValueString*/, "Time Off Policies"); }
function ShowExpenseAccountsGridView() { ShowStContent("EXPENSEACCNTGRID", ""/*ValueString*/, "Expense Accounts"); }
function ShowExpenseTypesGridView() { ShowStContent("EXPENSETYPEGRID", ""/*ValueString*/, "Expense Types"); }
function ShowExpenseTripsGridView() { ShowStContent("EXPENSETRIPGRID", ""/*ValueString*/, "Expense Trips"); }
function ShowExpenseTemplateGridView() { ShowStContent("EXPENSETEMPLATEGRID", ""/*ValueString*/, "Expense Templates"); }
function ShowMilestoneGridView() { ShowStContent("MILESTONEGRID", ""/*ValueString*/, "Billing Milestones"); }
function ShowEmailAccountsGridView() { ShowStContent("EMAILACCOUNTSGRID", ""/*ValueString*/, "Email Accounts"); }
function ShowEmailOutboxGridView() { ShowStContent("EMAILOUTBOXGRID", ""/*ValueString*/, "Email Outbox"); }
function ShowEmailSentGridView() { ShowStContent("EMAILSENTGRID", ""/*ValueString*/, "Email Sent"); }
function ShowRequiredScansGridView() { ShowStContent("BARCODEREQGRID", ""/*ValueString*/, "Required Scans"); }
function ShowBarcodeMacrosGridView() { ShowStContent("BARCODEMACROSGRID", ""/*ValueString*/, "Barcode Macros"); }
function ShowBarcodeRulesGridView() { ShowStContent("BARCODERULESGRID", ""/*ValueString*/, "Barcode Rules"); }
function ShowCustomReportsGridView() { ShowStContent("CUSTOMREPORTSGRID", ""/*ValueString*/, "Custom Reports"); }
function ShowScheduledReportsGridView() { ShowStContent("SCHEDULEDREPORTSGRID", ""/*ValueString*/, "Scheduled Reports"); }
function ShowScheduledReports() { ShowScheduledReportsGridView(); }
function ShowUsersGridView() { ShowStContent("USERSGRID", ""/*ValueString*/, "Users"); }
function ShowTimelogGridView() { ShowStContent("TIMELOGGRID", ""/*ValueString*/, "Time logs"); }
function ShowTimesheetGridView() { ShowStContent("TIMESHEET", ""/*ValueString*/, "Timesheet"); }
function ShowProjectsGridView() { ShowStContent("PROJECTSGRID", ""/*ValueString*/, "Projects"); }
function ShowClientsGridView() { ShowStContent("CLIENTSGRID", ""/*ValueString*/, "Clients"); }
function ShowCategoriesGridView() { ShowStContent("CATEGORIESGRID", ""/*ValueString*/, "Categories"); }
function ShowProjectTaskGridView() { ShowStContent("PROJTASKGRID", ""/*ValueString*/, "Project Tasks"); }
function ShowBarcodeRequiredScansGridView() { ShowStContent("BARCODEREQGRID", ""/*ValueString*/, "Required Scans"); }
function ShowScriptsGridView() { ShowStContent("SCRIPTGRID", ""/*ValueString*/, "Scripts"); }
function ShowPayPeriodsGridView() { ShowStContent("PAYPERIODSGRID", ""/*ValueString*/, "Pay Periods"); }
function ShowLockDateRangesGridView() { ShowStContent("LOCKDATERANGESGRID", ""/*ValueString*/, "Lock Date Ranges"); }
function ShowBarcodeView() { ShowStContent("BARCODESCAN", ""/*ValueString*/, "Scan Barcodes"); }
function ShowProjectTaskCalendarView() { ShowStContent("PROJTASKCALENDAR", ""/*ValueString*/, "Project Task Calendar"); }
function ShowUserLicensesGridView() { ShowStContent("LICENSESGRID", ""/*ValueString*/, "User Licenses"); }
function ShowCategoryGridView() { ShowStContent("CATEGORIESGRID", ""/*ValueString*/, "Categories"); }
function ShowInventoryGridView() { ShowStContent("INVENTORYGRID", ""/*ValueString*/, "Inventory"); }
function ShowInvoiceGridView() { ShowStContent("INVOICEGRID", ""/*ValueString*/, "Invoices"); }
function ShowToolControlGridView() { ShowStContent("TOOLCONTROLGRID", ""/*ValueString*/, "Tool Control"); }
function ShowTimesheetView() { ShowStContent("TIMESHEET", ""/*ValueString*/, "Timesheet"); }
function ShowTimelogCalendarView() { ShowStContent("TIMELOGCALENDAR", ""/*ValueString*/, "Time Log Calendar"); }
function ShowTimelogChartView() { ShowStContent("TIMELOGCHART", ""/*ValueString*/, "Time Log Chart"); }
function ShowExpenseGridView() { ShowStContent("EXPENSEGRID", ""/*ValueString*/, "Expenses"); }
function ShowExpenseCalendarView() { ShowStContent("EXPENSECALENDAR", ""/*ValueString*/, "Expense Calendar"); }
function ShowExpenseChartView() { ShowStContent("EXPENSECHART", ""/*ValueString*/, "Expense Chart"); }
function ShowTimeOffGridView() { ShowStContent("TIMEOFFGRID", ""/*ValueString*/, "Time Off"); }
function ShowTimeOffCalendarView() { ShowStContent("TIMEOFFCALENDAR", ""/*ValueString*/, "Time Off Calendar"); }
function ShowTimeOffChartView() { ShowStContent("TIMEOFFCHART", ""/*ValueString*/, "Time Off Chart"); }
function ShowWipJobGridView() { ShowStContent("WIP_GROUP_PROJ", ""/*ValueString*/, "Work In Progress"); }
function ShowWipEmployeeGridView() { ShowStContent("WIP_GROUP_EMPL", ""/*ValueString*/, "Employee Status"); }
function ShowResourceAllocationBarView() { ShowStContent("RA_RESALLOCBAR", ""/*ValueString*/, "Resource Allocation"); }
function ShowEmployeeAvailabilityBarView() { ShowStContent("RA_AVAILBAR", ""/*ValueString*/, "Availability"); }
function ShowHolidayGridView() { ShowStContent("HOLIDAYSGRID", ""/*ValueString*/, "Holidays"); }
function ShowScriptGridView() { ShowStContent("SCRIPTGRID", ""/*ValueString*/, "Scripts"); }
function ShowScheduledImports()  { ShowStContent("SCHEDULEDIMPORTSGRID", ""/*ValueString*/, "Scheduled Imports"); }
function ShowScheduledExports()  { ShowStContent("SCHEDULEDEXPORTSGRID", ""/*ValueString*/, "Scheduled Exports"); }
function ShowGoogleIntegration() { OpenGoogleIntegrationDialog(); }
function ShowScheduledScripts() { ShowStContent("SCHEDULEDSCRIPTSGRID", ""/*ValueString*/, "Scheduled Scripts"); }
function ShowAiProvidersGrid() { ShowStContent("AIGRID", ""/*ValueString*/, "AI Providers"); }
function ShowQbIntegration() { ShowStContent("QUICKBOOKS", ""/*ValueString*/, "QuickBooks"); }




function ShowDatabaseOptions() {

    // Just show static info from the current database connection
    AjaxPopupDatabaseConnectionStatus();
}


function ShowProjectAssistant() {

    OpenProjectAssistantDialog();
}

function ShowProjectTaskGridViewWithFilter(FilterJsonString) {
    ShowProjectTaskGridView();

    // Wait for the project tasks page to load
    // This could take some time
    // Use asynchronous setTimeout to wait...
    WaitForStContent("PROJTASKGRID", function (FilterJsonString) {

        // We're here!
        // Now wait a bit longer and try to set the filter choice
        setTimeout(function () {

            // Set the new filter choice, which has a built-in delay itself
            SetSelectedContentPaneFilterJsonString(FilterJsonString);

            // And now, a little longer for the function above to save, then refresh the contents
            setTimeout(function () {
                RefreshSelectedContent();
            }, 1000);
        }, 500);
    }, FilterJsonString);
}


/**
 * Wait for a page with the specified content to become available
 * This may take some time for the new tab to be created and the page loaded
 * Proceed to the callback when that content page is ready
 * GetSelectedContentType() should tell if the page is ready
 * @param {any} ContentType
 * @param {any} callback
 * @param {any} callbackobject
 */
function WaitForStContent(WaitForContentType, proceedcallback, proceedobject) {

    if (!WaitForContentType)
        return;
    if (!proceedcallback)
        return;

    var nAttempts = 0;
    var nMaxAttempts = 20;

    function tryProceed() {
        var ContentType = GetSelectedContentType();
        var sCurrentType = $('input[id="HiddenSelectedContentTypeId"]').val();

        if (ContentType === WaitForContentType && sCurrentType === WaitForContentType) {
            proceedcallback(proceedobject);
            return;
        }

        nAttempts++;
        if (nAttempts < nMaxAttempts)
            setTimeout(tryProceed, 100);
    }

    tryProceed();
}


function ShowAboutStandardTime() {

    var data = {
    };

    $.ajax({
        url: VirtualDirectory + "/Home/AjaxGetStandardTimeAboutMessage",
        type: "POST",
        data: JSON.stringify(data),
        dataType: "json",
        contentType: "application/json",
        success: function (response) {
            // Success
            if (response.Success) {
                PopupMessageBox(APP_NAME, response.Message);
            }
            else {
                ToastError("", response.ErrorResults);
            }
        },
        error: function (xhr, status, error) {
            var errormsg = "Error " + xhr.status + ", " + xhr.statusText;
            ToastError("ShowAboutStandardTime", errormsg);
            console.log('AJAX: ' + errormsg);
        }
    });
}


function ShowReportView(pathname) {

    // Add a new pane
    var NewContentPane = AddDocumentTab("REPORTVIEW", GetUniqueId(), pathname/*ValueString*/, "Report");
    if (NewContentPane)
        ActivateDocumentTabByPane(NewContentPane);
}

function ShowSpecificRecordsGrid(RecordTable, RecordIds) {

    // Add a new pane to display these specific records from this table
    var TableWithRecordIds = RecordTable + "~" + RecordIds;
    var NewContentPane = AddDocumentTab("SPECIFICRECORDSGRID", GetUniqueId(), TableWithRecordIds/*ValueString*/, "Records");
    if (NewContentPane)
        ActivateDocumentTabByPane(NewContentPane);
}



function ShowStandardTimeWebsite() {

    LaunchUrl(sBrandUrls.website || "https://www.strdtime.com/");
}

function ShowStandardTimeContactWebpage() {

    LaunchUrl(sBrandUrls.contact || "https://www.strdtime.com/contact");
}

function ShowStandardTimeVideoWebpage() {

    LaunchUrl(sBrandUrls.video || "https://www.strdtime.com/videos");
}

function ShowBarcodeScanVideoWebpage() {

    LaunchUrl(sBrandUrls.barcodeVideo || "https://www.strdtime.com/basic-barcode-setup-and-faq");
}

function ShowQuickBooksWebpage() {

    LaunchUrl(sBrandUrls.quickbooks || "https://www.strdtime.com/");
}

function ShowThingsToScanWebpage() {

    LaunchUrl(sBrandUrls.thingsToScan || "https://www.strdtime.com/things-to-scan-on-the-shop-floor");
}

function ShowYouTubeWebpage() {

    LaunchUrl(sBrandUrls.youTube || "https://www.youtube.com/subscription_center?add_user=scoutwestinc");
}


// Patches data-url on the three Standard Time ribbon buttons after the DOM is ready.
// Required because data-url is baked into the Razor HTML at render time; the click handler
// in standardtime-misc.js reads it at click time, so it must be overwritten here.
// Called from OnFullAppLoad(). No-ops for any key absent from sBrandUrls.
function ApplyBrandUrlsToRibbon() {

    if (sBrandUrls.website)  $('#StWebsiteButton').attr('data-url', sBrandUrls.website);
    if (sBrandUrls.youTube)  $('#YouTubeButton').attr('data-url', sBrandUrls.youTube);
    if (sBrandUrls.contact)  $('#SupportButton').attr('data-url', sBrandUrls.contact);
    if (sBrandUrls.store)    $('#BuyNowButton').attr('data-url', sBrandUrls.store);
}





function ShowBrowserCapabilities() {

    var width = $(window).width();
    var height = $(window).height();

    var sMsg = "";
    sMsg += "Width: " + width + "\r\n";
    sMsg += "Height: " + height + "\r\n";
    PopupMessageBox("Browser Capabilities", sMsg);
}



function OnImportMsProject() {

    OnImportMsProjectMpp();
}

function OnImportQuickBooks() {

    OnImportQuickBooksIif();
}




function GoTimesheetPreviousWeek() {
    // See HomeController.AjaxGetFilterJsonStringByWeekOffset() for hacky adaptation
    GoTimePeriodByWeekOffset(-1000/*Hack to adapt to older menus*/);
}

function GoTimesheetNextWeek() {
    // See HomeController.AjaxGetFilterJsonStringByWeekOffset() for hacky adaptation
    GoTimePeriodByWeekOffset(1000/*Hack to adapt to older menus*/);
}

function GoTimesheetThisWeek() {
    // See HomeController.AjaxGetFilterJsonStringByWeekOffset() for hacky adaptation
    GoTimePeriodByWeekOffset(0/*Hack to adapt to older menus*/);
}




function GoPreviousWeek() {
    GoTimePeriodByWeekOffset(-1/*nWeekOffset*/);
}

function GoNextWeek() {
    GoTimePeriodByWeekOffset(1/*nWeekOffset*/);
}

function GoThisWeek() {
    GoTimePeriodByWeekOffset(0/*nWeekOffset*/);
}




function GoNextOneWeek() {
    GoTimePeriodByWeekOffset(1/*nWeekOffset*/);
}

function GoPrevOneWeek() {
    GoTimePeriodByWeekOffset(-1/*nWeekOffset*/);
}





function GoTimePeriodByWeekOffset(nWeekOffset) {
    // Get the current FilterJsonString from the selected pane
    // Merge the current filter with the new filter
    // Then refresh the pane with the final filter results
    var CurrentFilterJsonString = GetSelectedContentPaneFilterJsonString();
    var ContentType = GetSelectedContentType();
    AjaxFilterByWeekOffset(ContentType, CurrentFilterJsonString, nWeekOffset/*0=this, -1=last, +1=next*/);
}



function ShowMsProjectIntegration() {

    ShowProjectTaskGridView();

    setTimeout(function () { OnExportMsProjectXML(); }, 250);
}

//function ShowQbIntegration() {

//    ShowTimelogGridView();

//    setTimeout(function () { OnExportQuickBooksTimer(); }, 250);
//}




//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//
//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//
//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//
// Navigate through content pages

var ContentArray = [];
var ContentPosition = -1;

// The most current content being displayed
var CurrentContentType = "";
var CurrentContentTitle = "";
var CurrentUniqueId = "";
var CurrentValueString = "";
var CurrentFilterJsonString = "";
var CurrentSettingsJsonString = "";

function AddToContentArray(ContentType, UniqueId, ValueString, ContentTitle, FilterJsonString, SettingsJsonString) {

    if (!ContentType)
        return;

    // Same content?
    var CurrentContentItem = GetCurrentContentItem();
    if (CurrentContentItem) {
        if (!CurrentContentItem.PropertiesGrid &&
            CurrentContentItem.ContentType === ContentType &&
            CurrentContentItem.ValueString === ValueString) {

            // Same content!
            return;
        }
    }

    var ContentItem = {};
    ContentItem.ContentType = ContentType;
    ContentItem.ContentTitle = ContentTitle;
    ContentItem.UniqueId = UniqueId;
    ContentItem.ValueString = ValueString;
    ContentItem.FilterJsonString = FilterJsonString;
    ContentItem.SettingsJsonString = SettingsJsonString;

    // Remember current content for filtering and settings
    SetupCurrentContentVars(ContentItem);

    // Cut off items at the end
    ContentArray.length = ContentPosition+1;
    ContentArray.push(ContentItem);
    ContentPosition++;

    // Enable buttons
    EnableBackForwardContent();
}

function AddPropertiesGridToContentArray(ObjectDataType, ObjectTable, ObjectRecordId, SelectedCellTable, SelectedCellColumnId) {

    if (!ObjectDataType)
        return;
    if (!ObjectTable)
        return;
    if (!ObjectRecordId)
        return;

    // Same content?
    var CurrentContentItem = GetCurrentContentItem();
    if (CurrentContentItem) {
        if (CurrentContentItem.PropertiesGrid &&
            CurrentContentItem.ObjectDataType === ObjectDataType &&
            CurrentContentItem.ObjectTable === ObjectTable &&
            CurrentContentItem.ObjectRecordId === ObjectRecordId &&
            CurrentContentItem.ObjectCellTable === SelectedCellTable &&
            CurrentContentItem.ObjectCellColumnId === SelectedCellColumnId) {

            // Same content!
            return;
        }
    }

    var ContentItem = {};
    ContentItem.PropertiesGrid = true;
    ContentItem.ObjectDataType = ObjectDataType;
    ContentItem.ObjectTable = ObjectTable;
    ContentItem.ObjectRecordId = ObjectRecordId;
    ContentItem.ObjectCellTable = SelectedCellTable;
    ContentItem.ObjectCellColumnId = SelectedCellColumnId;

    // Cut off items at the end
    ContentArray.length = ContentPosition + 1;
    ContentArray.push(ContentItem);
    ContentPosition++;

    // Enable buttons
    EnableBackForwardContent();
}

function AddFilterTreeToContentArray() {

    // Same content?
    var CurrentContentItem = GetCurrentContentItem();
    if (CurrentContentItem) {
        if (CurrentContentItem.FilterTree) {

            // Same content!
            return;
        }
    }

    var ContentItem = {};
    ContentItem.FilterTree = true;

    // Cut off items at the end
    ContentArray.length = ContentPosition + 1;
    ContentArray.push(ContentItem);
    ContentPosition++;

    // Enable buttons
    EnableBackForwardContent();
}






function OnBackContent() {

    if (!CanGoBackContent())
        return;

    ContentPosition--;
    var ContentItem = ContentArray[ContentPosition];
    RefreshSmallAppContentByItem(ContentItem);

    // Enable buttons
    EnableBackForwardContent();
}

function OnForwardContent() {

    if (!CanGoForwardContent())
        return;

    ContentPosition++;
    var ContentItem = ContentArray[ContentPosition];
    RefreshSmallAppContentByItem(ContentItem);

    // Enable buttons
    EnableBackForwardContent();
}

function RefreshSmallAppContentByItem(ContentItem) {

    if (!ContentItem)
        return;

    // Property grid
    if (ContentItem.PropertiesGrid) {
        AjaxRefreshPropertyGridView($("#"+PropertyGridPartialViewDivId), "OBJECT", ContentItem.ObjectDataType, ContentItem.ObjectTable, ContentItem.ObjectRecordId, ContentItem.ObjectCellTable, ContentItem.ObjectCellColumnId, ""/*PropertyValuesJsonString*/);
        return;
    }

    // Settings grid
    if (ContentItem.SettingsGrid) {
        AjaxRefreshSettingsGridView($("#"+SettingsGridPartialViewDivId), ContentItem.ContentType);
        return;
    }

    // Filter tree
    if (ContentItem.FilterTree) {
        AjaxRefreshFilterTreeView($("#"+FilterTreePartialViewDivId));
        return;
    }

    // Fill div with content
    SetupCurrentContentVars(ContentItem);
    RefreshSmallAppContentByValues(ContentItem.ContentType, ContentItem.ValueString, ContentItem.FilterJsonString, ContentItem.SettingsJsonString);
}

function RefreshSmallAppContentByValues(ContentType, ValueString, FilterJsonString, SettingsJsonString) {

    // Fill the content div
    var SmallAppContentDiv = $("#" + SmallAppContentDivId);
    AjaxRefreshPartialViewByContentType(SmallAppContentDiv, ContentType, ValueString);
}


function CanGoBackContent() {
    return (ContentPosition > 0);
}

function CanGoForwardContent() {
    return (ContentPosition < ContentArray.length - 1);
}

function GetContentArrayItemCount() {
    return ContentArray.length;
}

function EnableBackForwardContent() {

    var bCanGoBackContent = CanGoBackContent();
    var bCanGoForwardContent = CanGoForwardContent();

    var BackButton = $("#BackButton");
    var ForwardButton = $("#ForwardButton");
    if (!BackButton || !ForwardButton)
        return;

    if (bCanGoBackContent)
        SetButtonBackgroundImageFromAttributes(BackButton);
    else SetButtonBackgroundDisabledImageFromAttributes(BackButton);

    if (bCanGoForwardContent)
        SetButtonBackgroundImageFromAttributes(ForwardButton);
    else SetButtonBackgroundDisabledImageFromAttributes(ForwardButton);
}

function GetCurrentContentItem() {

    if (ContentPosition < 0)
        return null;
    if (ContentPosition >= ContentArray.length)
        return null;

    var ContentItem = ContentArray[ContentPosition];
    return ContentItem;
}

function SetupCurrentContentVars(ContentItem) {

    // The most current content being displayed
    if (!ContentItem)
        return;
    if (ContentItem.PropertiesGrid)
        return;
    if (ContentItem.SettingsGrid)
        return;
    if (ContentItem.FilterTree)
        return;

    // Remember current content for filtering and settings
    CurrentContentType = ContentItem.ContentType;
    CurrentContentTitle = ContentItem.ContentTitle;
    CurrentUniqueId = ContentItem.UniqueId;
    CurrentValueString = ContentItem.ValueString;
    CurrentFilterJsonString = ContentItem.FilterJsonString
    CurrentSettingsJsonString = ContentItem.SettingsJsonString
}


function GetCurrentContentType() {
    return CurrentContentType;
}

function GetCurrentContentTitle() {
    return CurrentContentTitle;
}

function GetCurrentFilterJsonString() {
    return CurrentFilterJsonString;
}

function GetCurrentSettingsJsonString() {
    return CurrentSettingsJsonString;
}

function GetCurrentValueString() {
    return CurrentValueString;
}

function GetCurrentUniqueId() {
    return CurrentUniqueId;
}


function ShowProjectTaskLinksForm(args) {

    var menucmd = [];
    if (Array.isArray(args)) {
        menucmd = args[0];
    }

    // Got a record?
    if (!menucmd || !menucmd.SenderRecordset || !menucmd.SenderRecordset.recordid) {
        ToastError("Task Links", "Select a project task record to view its incoming and outgoing links.");
        retturn;
    }

    // menucmd.SenderRecordset.datatype, menucmd.SenderRecordset.tablename, menucmd.SenderRecordset.recordid
    OpenProjectTaskLinkDetailsDialog(menucmd.SenderRecordset.recordid);
}






/**
 * Use this to pop open a modal dialog or dropdown in a property grid
 * See AddTriggerPropertyGridEditor()
 * This function finds the specified property then calls its editor
 * The result is a popup edit session
 * @param {any} RecordsetObject
 * @param {any} sDbTable
 * @param {any} sDbRecordId
 * @param {any} sPropertyName
 * @param {any} sDbProperty
 */
function TriggerPropertyGridEditor(RecordsetObject, sDbTable, sDbRecordId, sPropertyName, sDbProperty) {

    // Did the caller send an array with all the values inside?
    // If so, reassign parameter values from the array elements
    if (Array.isArray(RecordsetObject) && sDbTable === undefined && sDbRecordId === undefined && sPropertyName === undefined && sDbProperty === undefined) {
        RecordsetObject = arguments[0][0];
        sDbTable        = arguments[0][1];
        sDbRecordId     = arguments[0][2];
        sPropertyName   = arguments[0][3];
        sDbProperty     = arguments[0][4];
    }

    if (!sDbTable)
        return;
    if (!sDbRecordId)
        return;
    if (!sPropertyName)
        return;
    if (!sDbProperty)
        return;

    // The property panel must be visible for this to work
    // Search for the specified property div once the properties are alive
    ShowRecordsetProperties(sDbTable, sDbRecordId);


    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Search for a div with the sDbProperty in data-propertyid or sPropertyName in data-propertyname
    // This is the property being triggered
    // This requires that the property grid is displayed for this recordset
    /*
        <div id="" class="d-flex align-items-center container propertycontainer" data-propertytype="stdata.MultilineDialogRecordsetTextProperty" data-propertyname="Tasks" data-propertyid="Tasks_Property" data-objecttype="stdata.ProjectSet" data-objecttable="Projects" data-objectid="73364BA7-B2E0-4A65-8340-B6AA7C0D22F6" style="white-space: nowrap; font-size: calc(7pt + 0.25vw);" onclick="OpenRecordsetMultilineModalDialog('73364BA7-B2E0-4A65-8340-B6AA7C0D22F6', 'Projects', 'Tasks_Property', 'Tasks');">
          <div style="width: 95%; margin-right:4px; overflow: hidden;">Finishing
          some text....
          </div>
            <img src="" style="">
          </div>
    */
    // data-propertytype="stdata.MultilineDialogRecordsetTextProperty"
    // data-objecttype="stdata.ProjectSet"
    // data-objecttable="Projects"
    // data-objectid="73364BA7-B2E0-4A65-8340-B6AA7C0D22F6"
    // data-propertyname="Tasks"
    // data-propertyid="Tasks_Property"
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////


    // Find and click the div to activate the property editor
    // Search until the property grid is alive and displaying the specified property
    // Once it is found, it can be clicked to activate the editor
    FindPropertyGridDiv(sDbTable, sDbRecordId, sDbProperty, sPropertyName).then(function ($div) {
        if (!$div) {
            ToastError("Open Properties", "Choose View > Properties to use this function.");
            return;
        }

        // Click the div to activate the editor
        $div[0].click();
    });
}





/**
 * Search for a property grid row div by data-propertyid or data-propertyname attributes
 * Retries up to nMaxAttempts times with setTimeout() to allow async rendering.
 * Returns a Promise that resolves with the matched jQuery element, or null on failure.
 * @param {string} sDbProperty   - value to match against data-propertyid
 * @param {string} sPropertyName - value to match against data-propertyname
 * @returns {Promise<jQuery|null>}
 */
// Polls the DOM for a property grid row matching the given DB table, record ID, and property.
// Resolves with the first matching jQuery element, or null if not found after max attempts.
// sDbTable     - data-objecttable attribute value identifying the DB table (required)
// sDbRecordId  - data-objectid attribute value identifying the record (required)
// sDbProperty  - data-propertyid attribute value; tried first
// sPropertyName - data-propertyname attribute value; fallback when sDbProperty yields no match
function FindPropertyGridDiv(sDbTable, sDbRecordId, sDbProperty, sPropertyName) {

    return new Promise(function (resolve) {

        var nAttempts = 0;
        var nMaxAttempts = 100;
        var nDelayMs = 100;
        var bDialogOpened = false;

        function done($result) {
            if (bDialogOpened)
                ClosePleaseWaitDialog();
            resolve($result);
        }

        function tryFind() {
            var $el = $();

            // Step 1: find candidates by property ID, then fall back to property name
            if (sDbProperty)
                $el = $('[data-propertyid="' + sDbProperty + '"]');

            if (!$el.length && sPropertyName)
                $el = $('[data-propertyname="' + sPropertyName + '"]');

            // Step 2: narrow candidates to the row belonging to the target table and record
            if ($el.length) {
                var $filtered = $el.filter(function () {
                    return $(this).attr('data-objecttable') === sDbTable &&
                           $(this).attr('data-objectid') === sDbRecordId;
                });
                if ($filtered.length) {
                    done($filtered.first());
                    return;
                }
            }

            // Step 3: retry until the element appears or attempts are exhausted
            nAttempts++;

            // Step 4: open a please-wait dialog once polling exceeds 10 attempts
            if (nAttempts > 10 && !bDialogOpened) {
                OpenPleaseWaitDialog("Loading Properties");
                bDialogOpened = true;
            }

            if (nAttempts < nMaxAttempts)
                setTimeout(tryFind, nDelayMs);
            else
                done(null);
        }

        tryFind();
    });
}




function ShowRecordsetProperties(sDbTable, sDbRecordId) {

    // Open the properties panel and show the properties for this recordset
    var ObjectDataType = "stdata.BaseDataSet";

    // Fill properties with partial view from server
    AjaxRefreshPropertyGridView($("#" + PropertyGridPartialViewDivId), "OBJECT", ObjectDataType, sDbTable, sDbRecordId, ""/*sSelectedCellDbTable*/, ""/*sSelectedCellDbColumn*/, ""/*PropertyValuesJsonString*/);
    AddPropertiesGridToContentArray(ObjectDataType, sDbTable, sDbRecordId, ""/*sSelectedCellDbTable*/, ""/*sSelectedCellDbColumn*/);

    // Show the panel
    ShowPropertiesPane();

}


function ShowAutoScheduleProjectTasks() {

    OpenAutoScheduleDialog();
}

function OpenAutoScheduleDialog() {

    var nDlgWidth = 500;
    var nDlgHeight = 200;
    var nWindowWidth = $(window).width();
    var nWindowHeight = $(window).height();
    if (nWindowWidth < nDlgWidth)
        nDlgWidth = nWindowWidth * 0.95;
    if (nWindowHeight < nDlgHeight)
        nDlgHeight = nWindowHeight * 0.95;

    // Open the dialog
    // igniteui.com/help/igdialog-property-reference
    $("#igDialogAutoSchedule").igDialog({ modal: true, headerText: "Auto-Schedule Jobs", width: nDlgWidth, height: nDlgHeight, resizable: true, closeOnEscape: true, openAnimation: "", closeAnimation: "fade"/*, openAnimation: "fade"*/ });
    $("#igDialogAutoSchedule").igDialog("open");

    $('#igDialogAutoScheduleProgressBar').val(0);
    $("#igDialogAutoScheduleDetailsLabel").html("");

    CenterDialog("igDialogAutoSchedule");

    // Restart button click
    $("#igDialogAutoScheduleRestartButton").unbind().click(function () {
        //$("#igDialogAutoScheduleRestartButton").prop('disabled', true);
        AjaxRefreshAutoScheduleDialog(true, ""/*AutoScheduleId*/);
    });

    // Cancel button click
    $("#igDialogAutoScheduleCloseButton").unbind().click(function () {
        CloseAutoScheduleDialog();
    });

    // Set up controls
    //$("#igDialogAutoScheduleRestartButton").prop('disabled', true);
    AjaxRefreshAutoScheduleDialog(true, ""/*AutoScheduleId*/);
}

//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//
// Close the login dialog
//\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\////\\//
function CloseAutoScheduleDialog() {
    $("#igDialogAutoSchedule").igDialog("close");
    bAutoScheduleDialogIsOpen = false;
}

function IsAutoScheduleOpen() {
    return bAutoScheduleDialogIsOpen;
}



function AjaxRefreshAutoScheduleDialog(bRestart, AutoScheduleId) {

    var params = {
        "Restart": bRestart,
        "AutoScheduleId": AutoScheduleId,
    };

    $.ajax({
        url: VirtualDirectory + "/Home/AjaxGetAutoScheduleStatus",
        type: "POST",
        data: JSON.stringify(params),
        contentType: "application/json",
        success: function (response) {

            if (response.Success) {
                // { Success = true, Complete = bComplete, PercentComplete = nPercentComplete, Progress = sProgress, AutoScheduleProjectTasksId = AutoScheduleProjectTasks.GetGUID(), }
                $('#igDialogAutoScheduleProgressBar').val(response.PercentComplete);
                $("#igDialogAutoScheduleDetailsLabel").html(response.Progress);
                if (response.Complete) {
                    $("#igDialogAutoScheduleRestartButton").prop('disabled', false);
                }
                else {
                    setTimeout(function () { AjaxRefreshAutoScheduleDialog(false, response.AutoScheduleProjectTasksId); }, 100);
                }
            }
            else {
                ToastError("AjaxRefreshAutoScheduleDialog", response.ErrorResults);
            }
        },
        error: function (xhr, status, error) {
            var errormsg = "Error " + xhr.status + ", " + xhr.statusText;
            ToastError("AjaxRefreshAutoScheduleDialog", errormsg);
            console.log('AJAX: ' + errormsg);
        }
    });

}


/**
 * If nRecords exceeds 20, shows a Yes/No confirmation warning about token costs before proceeding.
 * Calls proceedcallback immediately if the count is within the threshold.
 * proceedcallback is passed as the Yes-callback to PopupYesNoWithCallback because that dialog is
 * asynchronous — a simple if/return guard cannot wait for the user's answer. Must use a callback for Yes answer
 * 
 * Explanation:
 *      Only proceed if the user answers Yes to the number of records to be sent to AI for analyis and updates
 *      Sending a large number of records to ai could result in high token usage and costs
 *      Warn the user first, then proceed if Yes
 * @param {number} nRecords
 * @param {function} proceedcallback
 */
function CheckAskSendNumberOfRecordsToAi(nRecords, proceedcallback) {
    if (nRecords > 20) {
        var sConfirmMsg = "There are " + nRecords + " records. Sending this many records to AI may use a significant number of tokens. There may be costs associated with this.\r\n\r\nDo you want to proceed?";
        PopupYesNoWithCallback("Chat With AI", sConfirmMsg, proceedcallback, null);
    } else {
        proceedcallback();
    }
}



