
// MARK: helper functions

function layoutForColumn(name)
{
	var headingName = "_" + name + "Hdr";
	return [
		`V:[${headingName}]-(<=999)-[${name}]&alignLeft`,
		`H:[${name}(==${headingName})]`,
	];
}

function sortDescriptor(sortKey, ascending, standardCompare)
{
	standardCompare = standardCompare || false;
	
	return {
		nsClass: "NSSortDescriptor",
		gxSortKey: sortKey,
		gxAscending: ascending,
		gxUseLocalisedStandardCompare: standardCompare,
	};
}

function columnSpec(name, displayName, width, minWidth, maxWidth, hidden, sortKey, standardCompare, preventHiding)
{
	var sortUp = [];
	var sortDown = [];
	if (sortKey != null)
	{
		sortUp = [ sortDescriptor(sortKey, true, standardCompare), sortDescriptor("name", true, true) ];
		sortDown = [ sortDescriptor(sortKey, false, standardCompare), sortDescriptor("name", true, true) ];
	}
	
	preventHiding = preventHiding || false;
	
	return {
		nsClass: "GXColumnSpec",
		gxName: name,
		gxDisplayName: displayName,
		gxPreventHiding: preventHiding,
		gxRightSizerName: name + "Sizer",
		gxSize: width,
		gxMin: minWidth,
		gxMax: maxWidth,
		gxHidden: hidden,
		gxSortUpDescriptors: sortUp,
		gxSortDownDescriptors: sortDown,
	};
}

function sizerSpec(name, displayName, leftColumn)
{
	return {
		nsClass: "GXColumnSpec",
		gxIsColumn: false,	// a splitter is not a column
		gxName: name,
		gxDisplayName: displayName,
		gxResizeColumn: leftColumn,
	};
}


function columnView(name)
{
	return {
		nsClass: "GXColumnView",
		gxValueKey: "columnSpecs." + name,
		gxCopyValues: true,
		axIsIgnored: false,
		axRoleDescription: "Column heading",
		gxLayout: [
			"V:|-0-[self(18)]",
			"H:|-0-[self]",
		],
		gxForePainter:
		{
			"+": "LabelFore.size12.left",
			gxFontColor: "ForeColor3",
			up: {
				gxFontWeight: 0.23, // medium fontweight
				gxFontColor: "ForeColor2",
				gxEdgeInsets: "0, 0, 17, 0",
			},
			down: {
				gxFontWeight: 0.23, // medium fontweight
				gxFontColor: "ForeColor2",
				gxEdgeInsets: "0, 0, 17, 0",
		   },
		},
		gxBackPainter: {
			"+": "ImagePainter.right.foreColor2.chevron",	// chevron doesn't exist - 'chevron.up' and 'chevron.down' do
			gxEdgeInsets: "0, 2, 6, 0",
		},
	};
}


function sizerView(name, canResize)
{
	if (canResize == null)
		canResize = true;

	return {
		nsClass: "GXSplitterView",
		gxValueKey: "columnSpecs." + name,
		gxCopyValues: true,
		gxCanResize: canResize,
		gxLayout: [
			"V:|-0-[self(18)]",
			"H:|-0-[self(8)]",
		],
		gxBackPainter: {
			nsClass: "GXPainter",
			gxFrameColor: "BackColor3",
			gxEdgeInsets: "-1, -1, 4, -1",
		},
	};
}



// --------------------------------------------------


markup.push(
{

// MARK: - home model

HomeModel:
{
	gxLeftWidth: 15,
	gxRightWidth: 14,
	gxColumnSpecs: [
		columnSpec("name", "Name", 182, 100, 400, false, "name", true, true),	 	// last true = prevent user hiding
		sizerSpec("nameSizer"),

		columnSpec("sources", "Sources", 80, 50, 160, false),
		sizerSpec("sourcesSizer"),

		columnSpec("autoRun", "Auto Run", 80, 80, 140, false, "autoStart", false),
		sizerSpec("autoRunSizer"),

		columnSpec("timers", "Timers", 45, 40, 120, true, "timersCount", false),
		sizerSpec("timersSizer"),

		columnSpec("recordings", "Recordings", 65, 50, 120, false, "recordingsCount", false),
		sizerSpec("recordingsSizer"),

		columnSpec("meter", "Meter", 105, 35, 210, false),
		sizerSpec("meterSizer"),

		columnSpec("homeStatus", "Status", 103, 103, 160, false, "statusSortValue", false),
		sizerSpec("homeStatusSizer"),

		columnSpec("control", "Run", 72, 40, 90, false),
		sizerSpec("controlSizer"),
	],
},
	
	
// MARK: - home window

HomeWindow:
{
	nsClass: "GXWindow",
	gxWindowTitle: "Audio Hijack Session List",
	gxCanFullScreen: true,
	gxWindowMaxSize: "4000, 2000",
	gxWindowMinSize: "400, 480",
	gxInitialWindowSize: "800, 540",
	gxInitialWindowPosition: "0.5, 0.22",
	gxBackColor: "BackColor2",
	gxSavedWindowStateKey: "homeWindowState",		// updated from 'homeWindow' when 410 added columns
	gxContentView: "HomeWindowContentView",
    gxFullSizeContentView: true,
},


// MARK: content view

HomeWindowContentView:
{
	nsClass: "GXDrawView",
    gxBackPainter: fillPainter("SidebarBackColor2"),
	gxWantsLayer: true,
	gxLayout:
	[
		"V:[titleBarView(27)]-3-[headings(23)]-0-[sessionsScrollView]-0-[trialBar]-0-[bottomBar(45)]-0-|",
	 	"V:[headings]-0-[windowDropView]-0-[trialBar]",
		"V:[headings]-0-[emptyView]-0-[trialBar]",

		"H:|-0-[headings]-0-|",
		"H:|-0-[sessionsList]-0-|",
		
		// fix window size to match columns
		"H:|-0-[self]-0-[endGuide]",		// window is sized to our column endGuide view

		// alternate version: constrain for allowing horizontal scroll but no empty space
		// (commented here to save time if ever needed again, but would require floating header etc too)
		//"H:|-0-[self]-(>=-16)-[endGuide]",	// window is sized to our column endGuide view
		//"H:[sessionsList]-0-[_endGuide]",		// document view sized to endguide

		"H:|-0-[sessionsScrollView]-0-|",
		"H:|-0-[windowDropView]-0-|",
		"H:|-0-[emptyView]-0-|",
		"H:|-0-[trialBar]-0-|",
	],
	gxChildViews:
	{
		titleBarView:
		{
			"+": "TitleBarView",
            gxBackPainter:
            {
                nsClass: "GXPainter",
                gxFillColor: "SidebarBackColor2",
                gxFrameColor: "BackColor3",
                gxEdgeInsets: "-1, -1, -1, 0",
            },
			gxChildViews:
			{
				windowTitle: {
					"+": "WindowTitle",
					gxDefaultValue: "Audio Hijack Session List",
				},
			},
		},
		headings: {
			"+": "SessionListHeadings",
			gxIntrinsicWidth: -1,
		},
		windowDropView:
		{
			nsClass: "GXDropView",
			acceptDroppedSessions: true,
			gxValueKey: "droppedFiles",
			gxLayerZPosition: 10,
			gxHilitePainter: {
				"+": "DropHilitePainter",
				gxCornerRadius: 0,
			},
		},
		emptyView: {
			"+": "EmptyHomeView",
		},
		sessionsScrollView:
		{
			nsClass: "GXScrollView",
			gxShowOnKey: "headingsShown",
			gxBackColor: "SidebarBackColor2",
			gxVScrollbar: "ScrollBarView",
			gxScrollbarWidth: 12,
			gxCornerFillView: filledView("SidebarBackColor2"),
			gxAddViewBelow: true,
			gxDocumentView:
            {
				// MARK: : list view
                nsClass: "GXListView",
                gxViewName: "sessionsList",
				gxDeleteKey: "deleteBtnValue",
				gxListItemView: "SessionListItem",
				gxItemHeight: 40,
				gxInterItemHeight: 1,
				gxTopHeight: 7,
				gxBottomHeight: 6,
				gxIntrinsicWidth: -1,
                axIsIgnored: false,
				axTitle: "Sessions",
				//axHelp: "List of all sessions",
				axDescriptionKeyPath: "sessionListDescription",
                axRoleDescription: "List",
			},
		},
        trialBar: {
            "+": "TrialBarView",
            gxViewModel: { nsClass: "AH4TrialBarViewModel" },
        },
		bottomBar:
		{
			// MARK: : bottom bar
			nsClass: "GXDrawView",
			gxBackPainter: "BottomBarBack",
			gxLayerZPosition: 10,
			gxLayout: [
				"H:|-0-[self]-0-|",
				"H:|-14-[newBtn(108)]-(>=14)-[deleteBtn(126)]-14-|&alignBaseline",
				"H:[self]-(<=0)-[newBtn]&alignCenterY",	// center vertically
				
				// VO info button too small to show up for regular users
				"V:[self]-0-[voiceOverInfoBtn(2)]&alignCenterX",
				"H:[voiceOverInfoBtn(1)]",
			],
			gxChildViews:
			{
				newBtn: {
					"+": "PlusButton",
					gxTitle: "<plusButton/> New Session",
					axDescription: "New session",
				},
				deleteBtn: {
					"+": "MinusButton",
					gxTitle: "<minusButton/> Delete Session",
					gxDisableOnNil: true,
					axDescription: "Delete selected sessions",
				},
				voiceOverInfoBtn: {
					// a button not visible to regular users, but will appear in navigation of VO users
					"+": "ButtonView",
					gxTitle: "Voice Over Help",
					axTitle: "Voice Over Help",
					axHelp: "VO press to open a Knowledge Base article for Voice Over users in your web browser",
					gxValueKey: "voiceOverInfoBtn",
				},
			}
		}
	}
},


// --------------------------------------------------------
// MARK: - session list items

SessionListItem:
{
	nsClass: "GXListItemView",
    gxViewName: "sessionItem",
	gxSelectable: 2,
	gxIntrinsicHeight: 40,
	axRoleDescription: "Session",
    axTitleKeyPath: "accessibilityDescription",
    axHelp: "VO press to open the session window. Interact for more controls.",
	gxBackPainter: {
		nsClass: "GXPainter",
		gxEdgeInsets: "6, 0, 3, 0",
		gxCornerRadius: 9.5,
		selected: { gxFillColor: "SelectionColor3", },
	},
    gxLateLayout:
    [
		"V:|-(-999)-[self]",	// vertical position set by parent
        "H:|-0-[self]-0-|",
		
		"V:|-8-[name(23)]",
		"V:|-7-[sources(27)]",
		"V:|-9-[autoRun(23)]",
		"V:|-0-[homeStatus(40)]",
		"V:|-3-[meterHostView(36)]",
		"V:|-9-[runBtn(22)]",
		"V:|-7-[recordings(27)]",
		"V:|-7-[timers(27)]",
	],
	gxChildViews:
	{
		name: {
			"+": "LabelView.foreColor1.size15.mediumWeight.left",
			gxValueKey: "name",
            axTitle: "Session Title",
            axIsIgnored: false,
			gxLateLayout: 	layoutForColumn("name"),
			gxLayerZPosition: 5,
			gxIntrinsicWidth: -1,
		},
		sources: {
			"+": "LabelView.foreColor1.left.clip.useMarkup.size14",
			gxValueKey: "graph.graphSources",
			gxLateLayout: 	layoutForColumn("sources"),
			gxLayerZPosition: 4,
			gxIntrinsicWidth: -1,
		},
		autoRun: {
			"+": "PopupMenuTemplate",
			gxValueKey: "autoStart",
			axTitle: "Auto Run",
			gxLateLayout: 	layoutForColumn("autoRun"),
			gxLayerZPosition:  0,
			gxIntrinsicWidth: -1,
            gxMenuItems:
            [
                menuItem("Off", 0),
                menuItem("On Launch", 1, "", "Launch"),
                //menuItem("At Login", 2, "", "Login"),
            ],
		},
		homeStatus: {
			"+": "LabelView",
            axTitle: "Status",
			gxLateLayout: 	layoutForColumn("homeStatus"),
			gxForePainter: {
				"+": "LabelFore.useMarkup.showAnimating.showSelected.centery.right",
				gxEdgeInsets: "0, 0, 26, 0",
			},
            axIsIgnored: false,
			gxLayerZPosition: 3,
			gxChildViews:
			{
				spinnerHost: {
					nsClass: "GXLayerHostingView",
					gxLateLayout: 	[
						"H:[self(21)]-0-|",
						"V:|-10-[self(21)]",
					],
					gxRootLayer:
					{
						nsClass: "GXCaarLayer",
						gxViewName: "spinner",
						gxAnimateOnKey: "running",
						gxHideOnNilValue: true,
						gxAnimationDivider: 2,
						gxCaarPainter: "RecordingSpinnerPainter",
					}
				},
			},
		},
        meterHostView: {
            nsClass: "GXLayerHostingView",
            gxLayerZPosition: 2,
			gxLateLayout: 	layoutForColumn("meterHostView"),
            gxRootLayer:
            {
                nsClass: "AH4SpecMeterLayer",
                gxValueKey: "specData",
                gxAnimateOnKey: "graph.started",
				gxAnimationDivider: 2,
                gxForePainter: {
                    nsClass: "GXPainter",
                    gxFillColor: "ColorThemeLive2",
                },
            }
        },
		runBtn: {
			"+": "RunButton.size13",
			gxLateLayout: 	layoutForColumn("runBtn"),
			gxLayerZPosition:  20,
		},
		recordings: {
			"+": "LabelView.centerx.foreColor2.mediumWeight.showSelected.size13",
			gxValueKey: "recordingsCount",
			gxLateLayout: 	layoutForColumn("recordings"),
			gxLayerZPosition:  3,
			axIsIgnored: false,
			axTitle: "Recordings Count",
			gxFormatter: { nsClass: "GXScaledFormatter", format: "%.0f", zeroFormat: "\u22C5" },	 // unicode 'Dot Operator', a nice dot
			axFormatter: { nsClass: "GXScaledFormatter", format: " %.0f "},	 // read zero rather than a dot, spaces needed for reading
			},
		timers: {
			"+": "LabelView.centerx.foreColor2.mediumWeight.showSelected.size13",
			gxValueKey: "timersCount",
			gxLateLayout: 	layoutForColumn("timers"),
			gxLayerZPosition:  3,
			axIsIgnored: false,
			axTitle: "Timers Count",
			gxFormatter: { nsClass: "GXScaledFormatter", format: "%.0f", zeroFormat: "\u22C5" },	 // unicode 'Dot Operator', a nice dot
			axFormatter: { nsClass: "GXScaledFormatter", format: " %.0f "},	 // read zero rather than a dot, spaces needed for reading
		},
	}
},

	
// --------------------------------------------------------
// MARK: session list headings

SessionListHeadings:
{
	nsClass: "GXDrawView",
	gxModelKeyPath: "columnsModel",
	gxBackPainter: {
		nsClass: "GXPainter",
		gxFillColor: "SidebarBackColor2",
		gxFrameColor: "BackColor3",
		gxEdgeInsets: "-1, -1, -1, 0",
	},
    axIsIgnored: false,
    axDescription: "Column headings",
	axHelp: "Interact to show, hide or sort columns",
	gxLateLayout:
	[
		"V:|-0-[columnsMenu(18)]",
		"H:[columnsMenu(17)]-2-|",
	],
	gxChildViews:
	{
        nameHdr: columnView("name"),
		nameSizer: sizerView("nameSizer"),
		sourcesHdr: columnView("sources"),
		sourcesSizer: sizerView("sourcesSizer"),
		autoRunHdr: columnView("autoRun"),
		autoRunSizer: sizerView("autoRunSizer"),
		homeStatusHdr: columnView("homeStatus"),
		homeStatusSizer: sizerView("homeStatusSizer"),
		meterHostViewHdr: columnView("meter"),
		meterSizer: sizerView("meterSizer"),
		runBtnHdr: columnView("control"),
		controlSizer: sizerView("controlSizer"),
		recordingsHdr: columnView("recordings"),
		recordingsSizer: sizerView("recordingsSizer"),
		timersHdr: columnView("timers"),
		timersSizer: sizerView("timersSizer"),
		endGuide: {
			nsClass: "GXSplitterView",
			gxValueKey: "endGuideSpec",
			gxCopyValues: true,
			gxLayout: [
				"V:|-(-1)-[self(0)]",
				"H:|-999-[self(0)]",
			],
		},
		columnsMenu:
		{
			nsClass: "GXPopupMenuView",
			gxForePainter: "ImagePainter.foreColor3.icon-columns",
			gxBackPainter: {
				nsClass: "GXCirclePainter",
				gxFillColor: "SidebarBackColor2",
				hover: { gxFillColor: "BackColor3" },
				gxDiameter: 17,
			},
			gxMenuItemsKeyPath: "columnsMenuItems",
			gxShowOnKey: "owner.headingsShown",
			gxPullsDown: true,
			axTitle: "Select Columns",
			axHelp: "Checked columns are shown in the Sessions list",
			gxHideOnNilValue: false,
			gxLayerZPosition: 10,
		},
	}
},


// --------------------------------------------------------
// MARK: - finalize on quit sheet

QuitFinalizingSheet:
{
	nsClass: "GXWindow",
	gxContentView: {
		nsClass: "GXDrawView",
		gxBackPainter: "QuitFinalizingSheetBack",
		gxLayout: [
			"H:|-0-[self(530)]-0-|",	// this determines window width
			"V:|-16-[title(20)]-8-[information(34)]-16-|",	// this determines sheet height
			"H:|-30-[title]-30-|",
			"H:|-30-[information]-30-|"
		],
		gxChildViews: {
			title: {
				"+": "LabelView.mediumWeight.size15",
				gxDefaultValue: "Audio Hijack is finalizing your recording",
				gxIntrinsicWidth: -1
			},
			information: {
				"+": "LabelView.left.top.size12.wrap",
				gxDefaultValue: "AAC and ALAC (.m4a) recordings are unplayable until necessary post-processing finishes. Audio Hijack will quit automatically once finalization is complete.",
				gxIntrinsicWidth: -1
			}
		}
	}
},

QuitFinalizingSheetBack: {
	nsClass: "GXPainter",
	gxFillColor: "BackColor2",
},


})
