class ez5.PdfCreator.Node extends CUI.ListViewTreeNode

	@getName: ->
		return "pdf-node"

	@getAvailableStyleSettings: ->
		if @styleSettings
			return @styleSettings
		@styleSettings =
			"class-name":
				group: "basic"
				field:
					type: CUI.Input
					name: "class_name"
					form: label: $$("pdf-creator.settings.node.class-name|label")
			"height":
				group: "basic"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.height|label")
					name: "height"
			"width":
				group: "basic"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.width|label")
					name: "width"
			"position-absolute":
				group: "extended"
				field:
					type: CUI.Checkbox
					form: label: $$("pdf-creator.settings.node.position-absolute|label")
					name: "position_absolute"
			"display":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.display|label")
					name: "display"
			"background":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.background|label")
					name: "background"
			"font-size":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.font-size|label")
					name: "font_size"
			"color":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.color|label")
					name: "color"
			"top":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.top|label")
					name: "top"
			"bottom":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.bottom|label")
					name: "bottom"
			"left":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.left|label")
					name: "left"
			"right":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.right|label")
					name: "right"
			"margin-top":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.margin-top|label")
					name: "margin_top"
			"margin-bottom":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.margin-bottom|label")
					name: "margin_bottom"
			"margin-left":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.margin-left|label")
					name: "margin_left"
			"margin-right":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.margin-right|label")
					name: "margin_right"
			"padding-top":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.padding-top|label")
					name: "padding_top"
			"padding-bottom":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.padding-bottom|label")
					name: "padding_bottom"
			"padding-left":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.padding-left|label")
					name: "padding_left"
			"padding-right":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.padding-right|label")
					name: "padding_right"
			"border-top":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.border-top|label")
					name: "border_top"
			"border-bottom":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.border-bottom|label")
					name: "border_bottom"
			"border-left":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.border-left|label")
					name: "border_left"
			"border-right":
				group: "extended"
				field:
					type: CUI.Input
					form: label: $$("pdf-creator.settings.node.border-right|label")
					name: "border_right"
		return @styleSettings

	initOpts: ->
		super()
		@addOpts
			name:
				check: String
			data:
				check: "PlainObject"
				default: {}
			children:
				check: (value) =>
					return CUI.util.isArray(value) and value.every((_value) -> _value instanceof ez5.PdfCreator.Node)

	name: ->
		return @_name

	readOpts: ->
		@_name = @constructor.getName()
		super()
		@setData(@_data)
		return @

	initChildren: ->
		@children = @children.filter((node) => node.isParentAllowed(@))
		return super()

	renderContent: ->
		@__internalNameLabel = new CUI.Label(text: @__getInternalName(), appearance: "secondary")
		horizontalLayout = new CUI.HorizontalLayout
			center: content: new CUI.Label(text: @getDisplayName())
			right: content: @__internalNameLabel
		return horizontalLayout.DOM

	allowRowMove: (to_node, newFather) ->
		if newFather == @getRoot() # The new father cannot be the root of the tree.
			return false
		return true

	# Returns true if **pdfNode** can be the parent of this node.
	isParentAllowed: (pdfNode) ->
		return pdfNode and pdfNode.name() in ["div", "document"]

	setData: (data) ->
		if not data.custom_css
			data.custom_css = $$("pdf-creator.settings.node.document.custom-css|placeholder")

		@__data = data

	getDisplayName: ->
		return $$("pdf-creator.node.#{@_name}.display-name")

	__getInternalName: ->
		return @getData().internal_name

	renderPdfContent: (opts) ->
		element = @__renderPdfContent(opts)
		@__addStyles(element)
		CUI.dom.addClass(element, "pdf-node")
		CUI.dom.addClass(element, "pdf-node-#{@name()}")

		data = @getData()
		if element and data.custom_css
			customStylesTag = @__createStyleElement(data.custom_css)
			CUI.dom.append(opts.head, customStylesTag)

		if opts.selectedNode == @
			CUI.dom.addClass(element, "pdf-node-selected")

		return element

	getSettingsForm: (opts = {}) ->
		panels = []

		# Get settings for the field.
		settingsFields = @__getSettingsFields()
		if @__showInternalNameField()
			settingsFields.unshift
				type: CUI.Input
				name: "internal_name"
				form: label: $$("pdf-creator.settings.node.document.internal-name|label")
				onDataChanged: =>
					@__internalNameLabel.setText(@__getInternalName())
					return

		# Create the panel with the general settings.
		if settingsFields.length > 0
			generalPanel = @__createPanelField(settingsFields, group: "general")
			panels.push(generalPanel)

		# Create the panels for style fields.
		for group, styleFields of @__getStyleFieldSettings()
			fields = styleFields.map((_field) -> _field.field)
			panelField = @__createPanelField(fields,
				group: group
				closed: group != "basic"
				name_in_form: true
			)
			panels.push(panelField)

		extraPanels = @getExtraSettingsPanels(opts)
		if extraPanels.length > 0
			panels = panels.concat(extraPanels)

		# Add a panel for custom css.
		if @__isCustomCSSEnabled()
			fields = [
				type: CUI.CodeInput
				mode: "css"
				name: "custom_css"
				maximize_horizontal: true
			]
			customCSSPanel = @__createPanelField(fields, group: "custom_css", closed: true)
			panels.push(customCSSPanel)

		if panels.length == 0
			return new CUI.Label(text: $$("pdf-creator.settings.node.no-settings|label"), centered: true, appearance: "secondary")

		@__form?.destroy()
		@__form = new CUI.Form
			fields: panels
			data: @getData()
			onDataChanged: (data, field) =>
				@__onDataChanged(data, field)
				opts.onDataChanged?(data, field)
		@__form.start()
		return @__form

	__createPanelField: (fields, opts = {}) ->
		if CUI.util.isUndef(opts.closed)
			opts.closed = false
		if CUI.util.isUndef(opts.name_in_form)
			opts.name_in_form = false # If true, the name of the group will be used as name of the form.
		group = opts.group

		field = new CUI.DataFieldProxy
			maximize_horizontal: true
			element: =>
				panel = new CUI.Panel
					text: $$("pdf-creator.settings.node.group-#{group}|label")
					closed: opts.closed
					radio: group
					content: =>
						form = new CUI.Form
							padded: true
							data: @getData()
							name: if opts.name_in_form then group
							fields: fields
						return form
				return panel
		return field

	getExtraSettingsPanels: (opts) ->
		return []

	# By default the data returned for saving is the same.
	# Override this method and implement something different in case that that data should be different when saving.
	getData: (isForSaving = false) ->
		return @__data

	getSaveData: ->
		_data = CUI.util.copyObject(@getData(true), true)
		data =
			name: @name()
			open: @isOpen()
			data: _data

		if not @children
			return data

		data.children = []
		for child in @children
			data.children.push(child.getSaveData())
		return data

	__isCustomCSSEnabled: ->
		true

	__showInternalNameField: ->
		true

	isCopyAllowed: ->
		return true

	copy: ->
		if not @isCopyAllowed()
			return

		opts =
			data: CUI.util.copyObject(@getData(), true)
			open: @isOpen()

		if @children
			opts.children = []
			for child in @children
				opts.children.push(child.copy())

		return new @constructor(opts)

	__addStyles: (element) ->
		if not element
			return

		styles = {}
		data = @getData()
		for group, fieldStyles of @__getStyleFieldSettings()
			for style in fieldStyles
				value = data[group]?[style.field.name]
				if CUI.util.isUndef(value)
					continue

				if style.name == "class-name"
					CUI.dom.addClass(element, value)
					continue

				if style.name == "position-absolute"
					if value # Value is false or true.
						styles["position"] = "absolute"
					continue

				styles[style.name] = value

		CUI.dom.setStyle(element, styles)
		return

	# Returns an object of fields with the settings defined in getStyleSettings.
	__getStyleFieldSettings: ->
		availableStyleSettings = ez5.PdfCreator.Node.getAvailableStyleSettings()
		styleSettings = @__getStyleSettings()
		styles = {}
		for styleName in styleSettings
			style = availableStyleSettings[styleName]
			if not style
				continue

			group = style.group
			if not styles[group]
				styles[group] = []

			styles[group].push(
				field: style.field
				name: styleName
			)
		return styles

	__getIdObjecttype: ->
		return @__getDocumentNode().getIdObjecttype()

	__getObjecttypeName: ->
		idObjecttype = @__getIdObjecttype()
		return ez5.schema.CURRENT._table_by_id[idObjecttype].name

	__getMask: ->
		return @__getDocumentNode().getMask()

	__getLayoutData: ->
		documentData = @__getDocumentNode().getData()
		layoutData =
			mode: documentData.layout_mode
			rows: documentData.layout_rows
			columns: documentData.layout_columns
			rowGap: documentData.row_gap
			columnGap: documentData.column_gap
			innerBorder: documentData.inner_border
			outerBorder: documentData.outer_border
		return layoutData

	__getDocumentNode: ->
		root = @getRoot()
		if root instanceof ez5.PdfCreator.Node.Document
			return root
		if root.children[0] instanceof ez5.PdfCreator.Node.Document
			return root.children[0]
		throw new Error("PdfNode.__getDocumentNode :: PdfDocumentNode not initialized correctly.")

	# Returns an element 'style' with the custom css.
	__createStyleElement: (styles) ->
		styleElement = CUI.dom.element("style")
		styles = styles.replace(/\r?\n|\r/g, "")
		CUI.dom.append(styleElement, styles)
		return styleElement

	### Methods to be implemented ###
	# Method executed when the data of the settings changes.
	__onDataChanged: (data, field) ->
		return

	# Array of settings fields.
	__getSettingsFields: ->
		return []

	# Array of strings with existing styles settings (see PdfNode.styleSettings).
	__getStyleSettings: ->
		return []

	# It is necessary to implement this method and return whatever it is wanted to render.
	__renderPdfContent: ->
		console.warn(CUI.util.getObjectClass(@)+".__renderPdfContent needs to be implemented.")

ez5.PdfCreator.plugins = new CUI.PluginRegistry(class: ez5.PdfCreator.Node)