class ez5.PdfCreator.Node.Document extends ez5.PdfCreator.Node.Body

	@FONT_AWESOME_CDN = "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"

	@getName: ->
		"document"

	@pageSizes =
		"A3":
			width: 29.7
			height: 42
		"A4":
			width: 21
			height: 29.7
		"A5":
			width: 14.8
			height: 21
		"B4":
			width: 25
			height: 35.3
		"B5":
			width: 17.6
			height: 25
		"Tabloid":
			width: 27.9
			height: 43.2
		"Legal":
			width: 21.6
			height: 35.6
		"Statement":
			width: 14
			height: 21.6
		"Executive":
			width: 18.4
			height: 26.7
		"Folio":
			width: 21.6
			height: 33
		"Letter":
			width: 21.6
			height: 27.9

	@FILE_EXTENSION = ".pdf"

	initOpts: ->
		super()

		@addOpts
			header:
				check: "PlainObject"
				default: {}
			footer:
				check: "PlainObject"
				default: {}
			idObjecttype:
				check: "Integer"
				mandatory: true
			idMask:
				check: "Integer"

	readOpts: ->
		super()

		# Mask Init
		@setMask()

		@__header = new ez5.PdfCreator.Header(data: @_header)
		@__footer = new ez5.PdfCreator.Footer(data: @_footer)
		return @

	isCopyAllowed: ->
		return false

	setMask: (maskId = @_idMask) ->
		mask = ez5.mask.CURRENT._mask_by_id[maskId]
		maskName = mask?.name or "_all_fields"
		@__mask = Mask.getMaskByMaskName(maskName, @_idObjecttype)
		return

	isParentAllowed: ->
		return false

	setData: (data) ->
		super(data)

		if not @__data.page_size
			@__data.page_size = "A4"

		if not @__data.margin_top
			@__data.margin_top = 1.016 # 0.4 inch
		if not @__data.margin_bottom
			@__data.margin_bottom = 1.016
		if not @__data.margin_left
			@__data.margin_left = 1.016
		if not @__data.margin_right
			@__data.margin_right = 1.016

		if not @__data.layout_mode
			@__data.layout_mode = "one_object"
		if not @__data.layout_rows
			@__data.layout_rows = 1
		if not @__data.layout_columns
			@__data.layout_columns = 1
		if not @__data.row_gap
			@__data.row_gap = 0
		if not @__data.column_gap
			@__data.column_gap = 0

		if not @__data.header_custom_html
			@__data.header_custom_html = $$("pdf-creator.settings.node.document.header_custom_html|placeholder")

		return

	renderContent: ->
		return (new CUI.Label(text: @getDisplayName())).DOM

	renderPdf: (_opts = {}) ->
		opts = CUI.Element.readOpts.call(@, _opts, "PdfDocumentNode.renderPdf",
			preview:
				check: Boolean
				default: false
			objects:
				check: (obj) ->
					CUI.util.isArray(obj) and obj.every((_o) -> CUI.util.isPlainObject(_o))
			selectedNode:
				check: ez5.PdfCreator.Node
			styles:
				check: String
			custom_css_url:
				check: String
		)

		html = @__getHtmlElement(opts)
		opts.head = html.children[0] # Add head element in opts so it is possible to add custom css.
		body = @renderPdfContent(opts)
		CUI.dom.append(html, body)
		return html

	__getHtmlElement: (opts) ->
		html = CUI.dom.$element("html", "pdf-print")
		head = CUI.dom.$element("head")
		CUI.dom.append(html, head)

		if opts.preview
			CUI.dom.addClass(html, "pdf-print-preview")

		data = @getData()
		if data.custom_css_url
			customLinkTag = @__createLinkElement(data.custom_css_url)
			CUI.dom.append(head, customLinkTag)

		if opts.styles
			stylesTag = @__createStyleElement(opts.styles)
			CUI.dom.append(head, stylesTag)

		if opts.custom_css_url
			customLinkTag = @__createLinkElement(opts.custom_css_url)
			CUI.dom.append(head, customLinkTag)

		headerCustomHTMLNodes = CUI.dom.htmlToNodes(data.header_custom_html)
		CUI.dom.append(head, headerCustomHTMLNodes)

		fontAwesomeLinkElement = @__createLinkElement(ez5.PdfCreator.Node.Document.FONT_AWESOME_CDN)
		CUI.dom.append(head, fontAwesomeLinkElement)
		return html

	__renderPdfContent: (opts) ->
		body = super(opts) # Renders the body.

		if opts.preview
			div = CUI.dom.div("pdf-print-preview-body")
			div.innerHTML = body.innerHTML
			if @__getLayoutData().outerBorder
				CUI.dom.addClass(div, "outer-border")
			CUI.dom.replace(body, div)

			# Margins and height/width in document are set in the settings of PDF print.
			# In preview is necessary to set them in the wrapper of the body.
			CUI.dom.setStyle(body,
				"padding-top": "#{@__data["margin_top"]}cm"
				"padding-bottom": "#{@__data["margin_bottom"]}cm"
				"padding-right": "#{@__data["margin_right"]}cm"
				"padding-left": "#{@__data["margin_left"]}cm"
			)

			footer = @renderFooter(opts)
			header = @renderHeader(opts)

			CUI.dom.prepend(body, header)
			CUI.dom.append(body, footer)

		return body

	getMaxCountPerPage: () ->
		layoutData = @__getLayoutData()
		if layoutData.mode == "one_object"
			return 1
		return layoutData.rows * layoutData.columns

	getFilename: (object) ->
		filename = @getData().filename or $$("pdf-creator.settings.node.document.filename-dafault-value")
		filename = ez5.PdfCreatorUtils.replaceTextPlaceholders(filename, object)

		if not filename.endsWith(ez5.PdfCreator.Node.Document.FILE_EXTENSION)
			filename += ez5.PdfCreator.Node.Document.FILE_EXTENSION
		return filename

	getExtraSettingsPanels: (opts = {}) ->
		headerFields = @__header.getSettingsFields(opts)
		footerFields = @__footer.getSettingsFields(opts)

		customHeadHTMLField =
			type: CUI.CodeInput
			mode: "html"
			name: "header_custom_html"
			maximize_horizontal: true

		panels = [
			@__createPanelField([customHeadHTMLField], group: "header_custom_html", closed: true)
			@__createPanelField(headerFields, group: "header", closed: true)
			@__createPanelField(footerFields, group: "footer", closed: true)
		]
		return panels

	getTemplateName: ->
		return @getData().template_name

	__getSettingsFields: ->
		data = @getData()

		onLayoutChanged = (field) =>
			form = field.getForm()
			fieldNames = [
				"inner_border"
				"layout_columns"
				"layout_rows"
				"row_gap"
				"column_gap"
			]

			for fieldName in fieldNames
				_field = form.getFieldsByName(fieldName)[0]
				if data.layout_mode == "one_object"
					_field.disable()
				else
					_field.enable()
			return

		colRowsOptions = [
			value: 1
		,
			value: 2
		,
			value: 3
		,
			value: 4
		,
			value: 5
		,
			value: 6
		,
			value: 7
		,
			value: 8
		,
			value: 9
		,
			value: 10
		]
		filenameHintButton = new CUI.Button
			text: $$("pdf-creator.settings.node.document.filename|hint")
			appearance: "flat"
			onClick: =>
				pop = new ez5.HintPopover
					element: filenameHintButton
					content: new CUI.Label(text: $$("pdf-creator.settings.node.document.filename-popover"), markdown: true)
					padded: true
				pop.show()

		fields = [
			type: CUI.MultiInput
			form: label: $$("pdf-creator.settings.node.document.template-name|label")
			control: ez5.loca.getLanguageControl()
			name: "template_name"
		,
			type: CUI.Input
			form:
				label: $$("pdf-creator.settings.node.document.filename|label")
				hint: filenameHintButton
			name: "filename"
		,
			type: CUI.Select
			form: label: $$("pdf-creator.settings.node.document.orientation|label")
			name: "orientation"
			options: [
				text: $$("pdf-creator.settings.node.document.orientation.option.portrait")
				value: false
			,
				text: $$("pdf-creator.settings.node.document.orientation.option.landscape")
				value: true
			]
		,
			type: CUI.Select
			form: label: $$("pdf-creator.settings.node.document.paper-size|label")
			name: "page_size"
			options: [
				text: "A3 (29.7 cm x 42.0 cm)"
				value: "A3"
			,
				text: "A4 (21.0 cm x 29.7 cm)"
				value: "A4"
			,
				text: "A5 (14.8 cm x 21.0 cm)"
				value: "A5"
			,
				text: "B4 (25.0 cm x 35.3 cm)"
				value: "B4"
			,
				text: "B5 (17.6 cm x 25.0 cm)"
				value: "B5"
			,
				text: "Tabloid (27.9 cm x 43.2 cm)"
				value: "Tabloid"
			,
				text: "Legal (21.6 cm x 35.6 cm)"
				value: "Legal"
			,
				text: "Statement (14.0 cm x 21.6 cm)"
				value: "Statement"
			,
				text: "Executive (18.4 cm x 26.7 cm)"
				value: "Executive"
			,
				text: "Folio (21.6 cm x 33.0 cm)"
				value: "Folio"
			,
				text: "Letter (21.6 cm x 27.9 cm)"
				value: "Letter"
			]
		,
			type: CUI.NumberInput
			form: label: $$("pdf-creator.settings.node.document.margin-top|label")
			name: "margin_top"
			decimals: 3
			min: 0
			max: 30
		,
			type: CUI.NumberInput
			form: label: $$("pdf-creator.settings.node.document.margin-bottom|label")
			name: "margin_bottom"
			decimals: 3
			min: 0
			max: 30
		,
			type: CUI.NumberInput
			form: label: $$("pdf-creator.settings.node.document.margin-left|label")
			name: "margin_left"
			decimals: 3
			min: 0
			max: 30
		,
			type: CUI.NumberInput
			form: label: $$("pdf-creator.settings.node.document.margin-right|label")
			name: "margin_right"
			decimals: 3
			min: 0
			max: 30
		,
			type: CUI.Checkbox
			form: label: $$("pdf-creator.settings.node.document.outer-border|label")
			name: "outer_border"
		,
			type: CUI.Options
			name: "layout_mode"
			form: label: $$("pdf-creator.settings.node.document.layout-mode|label")
			radio: true
			horizontal: false
			options: [
				text: $$("pdf-creator.settings.node.document.layout-mode.option.one-object")
				value: "one_object"
			,
				text: $$("pdf-creator.settings.node.document.layout-mode.option.multiple-objects")
				value: "multiple_objects"
			]
			onDataChanged: (_data, field) =>
				onLayoutChanged(field)
			onDataInit: onLayoutChanged
		,
			type: CUI.Select
			name: "layout_rows"
			form: label: $$("pdf-creator.settings.node.document.layout-rows|label")
			options: colRowsOptions
		,
			type: CUI.Select
			form: label: $$("pdf-creator.settings.node.document.layout-columns|label")
			name: "layout_columns"
			options: colRowsOptions
		,
			type: CUI.NumberInput
			decimals: 2
			min: 0
			max: 100
			form: label: $$("pdf-creator.settings.node.document.row-gap|label")
			name: "row_gap"
		,
			type: CUI.NumberInput
			decimals: 2
			min: 0
			max: 100
			form: label: $$("pdf-creator.settings.node.document.column-gap|label")
			name: "column_gap"
		,
			type: CUI.Checkbox
			form: label: $$("pdf-creator.settings.node.document.inner-border|label")
			name: "inner_border"
		,
			type: CUI.Input
			form: label: $$("pdf-creator.settings.node.document.custom-css-url|label")
			regexp: "^https?://[^/]+?([a-z0-9]|/.*)$"
			name: "custom_css_url"
		]

		return fields

	__createLinkElement: (url) ->
		linkElement = CUI.dom.element("link",
			rel: "stylesheet"
			href: url
		)
		return linkElement

	__getPageSizes: ->
		pageSize = @getData().page_size
		return ez5.PdfCreator.Node.Document.pageSizes[pageSize]

	getSaveData: ->
		data = super()
		data.header = @__header.getSaveData()
		data.footer = @__footer.getSaveData()
		data.idObjecttype = @_idObjecttype
		return data

	getWidth: ->
		sizes = @__getPageSizes()
		if @isLandscape()
			return sizes.height
		else
			return sizes.width

	getHeight: ->
		sizes = @__getPageSizes()
		if @isLandscape()
			return sizes.width
		else
			return sizes.height

	# Following methods are used as parameters for the creation of the PDF and not for the preview.
	isLandscape: ->
		return @getData().orientation # true for landscape, false for portrait.

	renderHeader: (opts) ->
		opts.documentNode = @
		return @__header.renderPdfContent(opts)

	renderFooter: (opts) ->
		opts.documentNode = @
		return @__footer.renderPdfContent(opts)

	getPaperWidth: ->
		sizes = @__getPageSizes()
		return @__cmToInch(sizes.width)

	getPaperHeight: ->
		sizes = @__getPageSizes()
		return @__cmToInch(sizes.height)

	getMargins: (inchUnit = true) ->
		margins = {}
		for side in ["top", "bottom", "left", "right"]
			margin = @__data["margin_#{side}"]
			margins[side] = if inchUnit then @__cmToInch(margin) else margin
		return margins

	__cmToInch: (cm) ->
		inches = cm / 2.54
		return Math.round(inches * 10) / 10

	__showInternalNameField: ->
		false

	getMask: ->
		return @__mask

	getIdObjecttype: ->
		return @_idObjecttype

	getHeader: ->
		return @__header

	getFooter: ->
		return @__footer
