note
	description: "[
		Dialog that submit exception as bug report to http://support.eiffel.com
	]"
	date: "$Date$"
	revision: "$Revision$"

class
	ES_EXCEPTION_SUBMIT_DIALOG

inherit

	ES_DIALOG
		rename
			make as make_dialog
		redefine
			on_after_initialized
		end

	SYSTEM_CONSTANTS
		export
			{NONE} all
		end

create
	make

feature {NONE} -- Initialization

	make (a_support_url: like support_url; a_comm: like support_login; a_last_description: like last_description)
			-- Set `last_description' with `a_description', `a_last_description' can be void
		require
			a_comm_attached: a_comm /= Void
			a_comm_is_support_accessible: a_comm.is_support_accessible
		do
			support_url := a_support_url
			support_login := a_comm
			last_description := a_last_description

			make_dialog
		ensure
			support_login_set: support_login = a_comm
			set: last_description = a_last_description
		end

	build_dialog_interface (a_container: EV_VERTICAL_BOX)
			-- Builds the dialog's user interface.
			--
			-- `a_container': The dialog's container where the user interface elements should be extended
		local
			l_vbox: EV_VERTICAL_BOX
			l_width: INTEGER
			l_user_label: EV_LABEL
			l_pass_label: EV_LABEL
			l_text: EV_LABEL
			l_link: EV_LINK_LABEL
			l_hbox: EV_HORIZONTAL_BOX
			l_shrinkable: EV_FIXED
			l_string: STRING_32
		do
			a_container.set_padding ({ES_UI_CONSTANTS}.vertical_padding)

			create login_frame.make_with_text (locale_formatter.translation (t_account_access))
			create l_vbox
			l_vbox.set_padding ({ES_UI_CONSTANTS}.vertical_padding)
			l_vbox.set_border_width ({ES_UI_CONSTANTS}.frame_border)
			login_frame.extend (l_vbox)


				-- Username and password
			create l_user_label.make_with_text (locale_formatter.translation (lb_username))
			l_user_label.align_text_right
			create l_pass_label.make_with_text (locale_formatter.translation (lb_password))
			l_pass_label.align_text_right
			l_width := l_user_label.width.max (l_pass_label.width)
			l_user_label.set_minimum_width (l_width)
			l_pass_label.set_minimum_width (l_width)

				-- Username
			create l_hbox
			l_hbox.set_padding ({ES_UI_CONSTANTS}.horizontal_padding)
			l_hbox.extend (l_user_label)
			l_hbox.disable_item_expand (l_user_label)
			create username_text
			username_text.set_minimum_width (190)
			register_action (username_text.change_actions, agent enable_login)
			suppress_confirmation_key_close (username_text)
			l_hbox.extend (username_text)

			l_vbox.extend (l_hbox)
			l_vbox.disable_item_expand (l_hbox)

				-- Password
			create l_hbox
			l_hbox.set_padding ({ES_UI_CONSTANTS}.horizontal_padding)
			l_hbox.extend (l_pass_label)
			l_hbox.disable_item_expand (l_pass_label)
			create password_text
			register_action (password_text.change_actions, agent enable_login)
			register_action (password_text.key_press_actions, agent on_password_key_pressed)
			suppress_confirmation_key_close (password_text)
			password_text.set_minimum_width (190)
			l_hbox.extend (password_text)

			l_vbox.extend (l_hbox)
			l_vbox.disable_item_expand (l_hbox)

				-- Remember me check
			create l_hbox
			l_hbox.set_padding ({ES_UI_CONSTANTS}.horizontal_padding)
			l_hbox.extend (create {EV_CELL})
			create remember_me_check.make_with_text (locale_formatter.translation (lb_remember_me))
			register_action (remember_me_check.select_actions, agent on_remember_me_toggled)
			l_hbox.extend (remember_me_check)
			l_hbox.disable_item_expand (remember_me_check)

			if session_manager.service = Void then
					-- Remembering the user's details uses the session manager service, so if it's unavailble then
					-- we there is no point showing the check mark
				remember_me_check.hide
			end

			create login_button.make_with_text (locale_formatter.translation (b_login))
			login_button.set_minimum_width ({ES_UI_CONSTANTS}.dialog_button_width)
			register_action (login_button.select_actions, agent on_login)
			suppress_confirmation_key_close (login_button)
			l_hbox.extend (login_button)
			l_hbox.disable_item_expand (login_button)

			l_vbox.extend (l_hbox)
			l_vbox.disable_item_expand (l_hbox)

				-- Register
			create l_hbox
			create l_text.make_with_text (locale_formatter.translation (lb_register_account))
			l_text.align_text_left
			create l_link.make_with_text (locale_formatter.translation (b_here))
			l_link.select_actions.extend (agent
				local
					l_uri_provider: RAW_URI_HELP_PROVIDER
					l_register_url: STRING_8
					l_error_info: STRING_8
					l_error: ES_ERROR_PROMPT
				do
					create l_uri_provider.make (
						agent (preferences.misc_data.internet_browser_preference).value)
					l_register_url := support_login.register_url
					if support_login.is_bad_request then
						l_error_info := "Unable to register due to network problem. Please try again later."
						create l_error.make_standard (l_error_info)
						l_error.show (dialog)
					else
						l_uri_provider.show_help (support_login.register_url, Void)
					end

				end)

			l_link.align_text_left
			l_hbox.extend (l_text)
			l_hbox.disable_item_expand (l_text)
			l_hbox.extend (l_link)
			l_hbox.disable_item_expand (l_link)

			l_vbox.extend (l_hbox)
			l_vbox.disable_item_expand (l_hbox)

			create l_shrinkable
			l_shrinkable.extend (login_frame)
			shrink_widget := l_shrinkable

			l_shrinkable.resize_actions.extend (agent (a_x: INTEGER_32; a_y: INTEGER_32; a_width: INTEGER_32; a_height: INTEGER_32)
				do
					if a_width > 0 and a_height > 0 then
						shrink_widget.set_item_size (login_frame, a_width, a_height)
					end
				end)

			l_shrinkable.dpi_changed_actions.extend (agent (a_dpi: NATURAL_32; a_x: INTEGER_32; a_y: INTEGER_32; a_width: INTEGER_32; a_height: INTEGER_32)
				do
					if a_width > 0 and a_height > 0 then
						shrink_widget.set_item_size (login_frame, a_width, a_height)
					end
				end)

			a_container.extend (l_shrinkable)
			a_container.disable_item_expand (l_shrinkable)

				-- Logged in text
			create logged_in_label
			logged_in_label.align_text_left
			logged_in_label.hide

			create log_out_link.make_with_text (locale_formatter.translation (b_log_out))
			log_out_link.select_actions.extend (agent on_logout)
			log_out_link.align_text_left
			log_out_link.hide

			create l_hbox
			l_hbox.extend (logged_in_label)
			l_hbox.disable_item_expand (logged_in_label)
			l_hbox.extend (log_out_link)
			l_hbox.disable_item_expand (log_out_link)

			a_container.extend (l_hbox)
			a_container.disable_item_expand (l_hbox)

				--
				-- More bug information
				--
			create report_frame.make_with_text (locale_formatter.translation (t_bug_information))
			create l_vbox
			l_vbox.set_padding ({ES_UI_CONSTANTS}.vertical_padding)
			l_vbox.set_border_width ({ES_UI_CONSTANTS}.frame_border)
			report_frame.extend (l_vbox)

			a_container.extend (report_frame)

				-- Synopsis
			create synopsis_text
			synopsis_text.set_text (synopsis)
			register_action (synopsis_text.focus_in_actions, agent on_text_component_focused (synopsis_text))
			register_action (synopsis_text.focus_out_actions, agent on_text_component_focused_out (synopsis_text, locale_formatter.translation (lb_enter_synopsis)))
			suppress_confirmation_key_close (synopsis_text)
			l_vbox.extend (synopsis_text)
			l_vbox.disable_item_expand (synopsis_text)

				-- Description
			create description_text
			description_text.set_minimum_size (400, 100)
			register_action (description_text.focus_in_actions, agent on_text_component_focused (description_text))
			register_action (description_text.focus_out_actions, agent on_text_component_focused_out (description_text, default_description))
			suppress_confirmation_key_close (description_text)
			l_vbox.extend (description_text)

				-- Public bug
			create make_public_check.make_with_text (locale_formatter.translation (lb_make_public))
			l_vbox.extend (make_public_check)
			l_vbox.disable_item_expand (make_public_check)

				-- Severity
			create l_hbox
			l_hbox.set_padding ({ES_UI_CONSTANTS}.horizontal_padding)
			create severity_label.make_with_text (locale_formatter.translation (lb_severity))
			l_hbox.extend (severity_label)
			l_hbox.disable_item_expand (severity_label)
			create severity_critical_radio.make_with_text (locale_formatter.translation (i_critical))
			l_hbox.extend (severity_critical_radio)
			l_hbox.disable_item_expand (severity_critical_radio)
			create severity_serious_radio.make_with_text (locale_formatter.translation (i_serious))
			l_hbox.extend (severity_serious_radio)
			l_hbox.disable_item_expand (severity_serious_radio)
			create severity_non_critical_radio.make_with_text (locale_formatter.translation (i_non_critical))
			l_hbox.extend (severity_non_critical_radio)
			l_hbox.disable_item_expand (severity_non_critical_radio)
			l_vbox.extend (l_hbox)
			l_vbox.disable_item_expand (l_hbox)
			severity_serious_radio.enable_select

				-- Add items to login context
			--login_context_item.force_last (l_frame)

				-- Enable content items based on login state.
			on_text_component_focused_out (synopsis_text, locale_formatter.translation (lb_enter_synopsis))
			on_text_component_focused_out (description_text, default_description)
			if description_text.text_length > 0 then
				l_string := description_text.text
				if l_string.item (1).is_character_8 and then l_string.item (1).to_character_8.is_space then
						-- Rese the caret position, because the start of the text is blank.
					description_text.set_caret_position (1)
				end
			end
			enable_login
			enable_login_content_widget (False)

			set_button_text ({ES_DIALOG_BUTTONS}.ok_button, "Submit")
			set_button_action_before_close ({ES_DIALOG_BUTTONS}.ok_button, agent on_submit)

			description_text.focus_in_actions.extend (agent on_focus_in)
			description_text.focus_out_actions.extend (agent on_focus_out)
		end

	on_after_initialized
			-- Use to perform additional creation initializations, after the UI has been created.	
		do
			Precursor {ES_DIALOG}
			if is_user_remembered then
				username_text.set_text (remembered_username)
				password_text.set_text (remembered_password)
				remember_me_check.enable_select
				register_kamikaze_action (show_actions, agent on_login)
			end
		end

feature -- Query

	is_submit_successed: BOOLEAN
			-- If bug report submitted successfully

	user_description: STRING_32
			-- Text in `description_text'
		do
			if description_text /= Void then
				Result := description_text.text
			end
		end

feature -- Access

	icon: EV_PIXEL_BUFFER
			-- The dialog's icon
		once
			Result := (create {EV_STOCK_PIXMAPS}).error_pixel_buffer
		end

	title: STRING_32
			-- The dialog's title
		once
			Result := "Submit EiffelStudio Unhandled Exception"
		end

	buttons: DS_SET [INTEGER]
			-- Set of button id's for dialog
			-- Note: Use {ES_DIALOG_BUTTONS} or `dialog_buttons' to determine the id's correspondance.
		once
			Result := dialog_buttons.ok_cancel_buttons
		end

	default_button: INTEGER
			-- The dialog's default action button
		once
			Result := {ES_DIALOG_BUTTONS}.ok_button
		end

	default_confirm_button: INTEGER
			-- The dialog's default confirm button
		once
			Result := {ES_DIALOG_BUTTONS}.ok_button
		end

	default_cancel_button: INTEGER
			-- The dialog's default cancel button
			-- Note: The default cancel button is set on show, so if you want to change the
			--       default cancel button after the dialog has been shown, please see the implmentation
			--       of `show' to see how it is done.
		once
			Result := {ES_DIALOG_BUTTONS}.cancel_button
		end

feature {NONE} -- Implementation: access

	support_url: STRING
			-- Support site url.

	support_login: ESA_SUPPORT_BUG_REPORTER
			-- Reporter used to report bugs to the support system

	remembered_username: STRING_GENERAL
			-- Last remembered user name
		require
			is_interface_usable: is_interface_usable
			is_initialized: is_initialized or is_initializing
			is_user_remembered: is_user_remembered
		do
			if
				attached session_manager.service as l_session_service and then
				attached {STRING_GENERAL} session_data (l_session_service).value (username_session_id) as s
			then
				Result := s
			else
				create {STRING_32} Result.make_empty
			end
		ensure
			result_attached: Result /= Void
		end

	remembered_password: STRING_GENERAL
			-- Last remembered password
		require
			is_interface_usable: is_interface_usable
			is_initialized: is_initialized or is_initializing
			is_user_remembered: is_user_remembered
		do
			if
				attached session_manager.service as l_session_service and then
				attached {STRING_GENERAL} session_data (l_session_service).value (password_session_id) as s
			then
				Result := s
			else
				create {STRING_32} Result.make_empty
			end
		ensure
			result_attached: Result /= Void
		end

	default_description: attached STRING_32
			-- Default text for the bug report description
		do
			if attached last_description as d then
				create Result.make_from_string (d)
			else
				Result := locale_formatter.translation (lb_enter_bug_information)
			end
		end

	last_description: READABLE_STRING_GENERAL
			-- Last description

feature {NONE} -- Status report

	is_user_remembered: BOOLEAN
			-- Indicates if user login information was remembered
		require
			is_interface_usable: is_interface_usable
			is_initialized: is_initialized or is_initializing
		do
			if attached session_manager.service as l_session_service then
				if attached {BOOLEAN_REF} session_data (l_session_service).value_or_default (remembered_session_id, False) as l_ref then
					Result := l_ref.item
				end
			end
		end

	is_synopsis_available: BOOLEAN
			-- Determines if a synopsis has been entered by the user
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
		do
			Result := synopsis_text.text /= Void and then not synopsis_text.text.is_empty and then synopsis_text.text /~ (locale_formatter.translation (lb_enter_synopsis))
		end

	is_description_available: BOOLEAN
			-- Determines if a description has been entered by the user
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
		do
			Result := attached description_text.text as txt and then not txt.is_empty and then
				 not (txt.is_equal (default_description) and last_description = Void)
		end

	can_submit: BOOLEAN
			-- Determines if a report is submittable
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
		do
			Result := support_login.is_support_accessible and then support_login.is_logged_in
		end

feature {NONE} -- Action handlers

	on_login
			-- Called when user requests to log in
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
			is_support_accessible: support_login.is_support_accessible
		do
			on_remember_me_toggled
			execute_with_busy_cursor (agent
				local
					l_error: ES_ERROR_PROMPT
					l_error_info: STRING_32
				do
					login_button.disable_sensitive
					support_login.force_logout
					support_login.attempt_logon (username_text.text, password_text.text, remember_me_check.is_selected)
					if support_login.is_logged_in then
						logged_in_label.set_text ("You are currently logged in as " + username_text.text + " ")
						logged_in_label.show
						log_out_link.show

						login_frame.hide
						create shrink_timer.make_with_interval (shrink_interval)
						shrink_timer.actions.extend (agent on_shrink_interval_expired_for_collapse)
					else
						if support_login.is_bad_request then
							if attached support_login.last_error as ll_error then
								l_error_info := {STRING_32} "Unable to login due to network problem. Please try again later."
								l_error_info.append_character ('%N')
								l_error_info.append (ll_error)
							else
								l_error_info := {STRING_32} "Unable to login due to network problem. Please try again later."
							end
						else
							l_error_info := {STRING_32} "Unable to login with the specified user name and password. Please check and try again."
						end

						create l_error.make_standard (l_error_info)
						l_error.show (dialog)

						logged_in_label.hide
						log_out_link.hide
						login_button.enable_sensitive
						enable_login_content_widget (False)

							-- Set focus back to button, as it will have been the last focused widget
						login_button.set_focus
					end
				end
			)
		end

	on_logout
			-- Called when the user requests a log out of a current session
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
			is_support_accessible: support_login.is_support_accessible
		do
			logged_in_label.hide
			log_out_link.hide

			login_button.enable_sensitive
			enable_login_content_widget (False)
				-- The user wants to change the login, select the user name field
			if username_text.is_displayed then
				username_text.set_focus
			end

			create shrink_timer.make_with_interval (shrink_interval)
			shrink_timer.actions.extend (agent on_shrink_interval_expired_for_expand)
		end

	on_submit
			-- Call when user chooses to submit a bug report when `can_submit'
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
			is_support_accessible: support_login.is_support_accessible
		local
			l_warning: ES_WARNING_PROMPT
			l_error: ES_ERROR_PROMPT
			l_retried: BOOLEAN
		do
			if can_submit then
				if not l_retried then
					if not is_description_available then
						create l_warning.make_standard_with_cancel (locale_formatter.translation (w_no_description))
						l_warning.set_button_action ({ES_DIALOG_BUTTONS}.cancel_button, agent veto_close)
						l_warning.set_button_action ({ES_DIALOG_BUTTONS}.ok_button, agent do execute_with_busy_cursor (agent submit_bug_report) end)
						l_warning.show (dialog)
					else
						is_submit_successed := False
							-- is_submit_successed will be set by `submit_bug_report'
						execute_with_busy_cursor (agent submit_bug_report)
					end
				else
					create l_error.make_standard (locale_formatter.translation (e_submit_error))
					l_error.show (dialog)
				end
			end
		rescue
			l_retried := True
			retry
		end

	on_remember_me_toggled
			-- Called when the user toggles the "remember me" check box.
		require
			is_interface_usable: is_interface_usable
			is_initialized: is_initialized
		local
			l_remember: BOOLEAN
			l_session_data: like session_data
		do
			if attached session_manager.service as l_session_service then
				l_session_data := session_data (l_session_service)
				l_remember := remember_me_check.is_selected
				l_session_data.set_value (l_remember, remembered_session_id)
				if l_remember then
					l_session_data.set_value (username_text.text, username_session_id)
					l_session_data.set_value (password_text.text, password_session_id)
				else
						-- Clear remembered data
					l_session_data.set_value (Void, username_session_id)
					l_session_data.set_value (Void, password_session_id)
				end
					-- Store session information incase user selects to quit ES.
				l_session_service.store (l_session_data)
			end
		end

	on_shrink_interval_expired_for_collapse
			-- Called when `shrink_timer' interval expires when collapsing.
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
			shrink_timer_attached: shrink_timer /= Void
		do
			-- On Solaris, minimum height of `shrink_widget' is 1, not 0.
			-- On Windows, minimum height of `shrink_widget' is 0.
			if shrink_widget.height <= 1 then
				shrink_widget.set_minimum_height (0)
				shrink_timer.destroy
				shrink_timer := Void
				enable_login_content_widget (True)

					-- Set focus to description, now the fields are activated
				description_text.set_focus
			else
				shrink_widget.set_minimum_height ((shrink_widget.height - 4).max (0))
			end
		end

	on_shrink_interval_expired_for_expand
			-- Called when `shrink_timer' interval expires when expanding.
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
			shrink_timer_attached: shrink_timer /= Void
		do
			if shrink_widget.height = login_frame.height then
				shrink_timer.destroy
				shrink_timer := Void
				enable_login_content_widget (False)
				login_frame.show
			else
				shrink_widget.set_minimum_height ((shrink_widget.height + 4).min (login_frame.height))
			end
		end

	on_text_component_focused (a_text_widget: EV_TEXT_COMPONENT)
			-- Called when a registered text widget attains focused
			--
			-- `a_text_widget': The focused text_widget.
		require
			is_initialized: is_initialized or is_initializing
			not_is_recycled: not is_recycled
			a_text_widget_attached: a_text_widget /= Void
		local
			l_text: STRING_GENERAL
		do
			l_text := a_text_widget.text
			if l_text = Void or else l_text.is_case_insensitive_equal (default_description) then
				a_text_widget.set_foreground_color (colors.grid_item_text_color)
				if a_text_widget /= description_text or else last_description = Void then
					a_text_widget.remove_text
				end
			end
		end

	on_text_component_focused_out (a_text_widget: EV_TEXT_COMPONENT; a_default_text: READABLE_STRING_GENERAL)
			-- Called when a registered text widget loses focused
			--
			-- `a_text_widget': The unfocused text_widget.
			-- `a_default_text': The default text to show, if no text is available for the widget.
		require
			is_initialized: is_initialized or is_initializing
			not_is_recycled: not is_recycled
			a_text_widget_attached: a_text_widget /= Void
			a_default_text_attached: a_default_text /= Void
			not_a_default_text_is_empty: not a_default_text.is_empty
		local
			l_text: STRING_GENERAL
		do
			l_text := a_text_widget.text
			if l_text = Void or else l_text.is_empty then
				a_text_widget.set_foreground_color (colors.grid_disabled_item_text_color)
				a_text_widget.set_text (a_default_text)
			end
		end

	on_focus_in
			-- When the `description_text' has the focus, we disable the default push button.
		local
			l_dialog: EV_DIALOG
		do
			l_dialog := dialog
			if l_dialog /= Void and then
				(not l_dialog.is_destroyed and l_dialog.default_push_button /= Void) then
				l_dialog.remove_default_push_button
			end
		end

	on_focus_out
			-- When the `description_text' lost focus, we enable the default push button.
		local
			l_dialog: EV_DIALOG
			l_button: EV_BUTTON
		do
			l_dialog := dialog
			if l_dialog /= Void then
			l_button := dialog_window_buttons.item (default_button)
				if l_button /= Void and then
				 (not l_dialog.is_destroyed and l_dialog.has_recursive (l_button)) then
					l_dialog.set_default_push_button (l_button)
				end
			end
		end

	on_password_key_pressed (a_key: EV_KEY)
			-- When user pressed a key in `password_text'
		do
			if a_key /= Void and then a_key.code = {EV_KEY_CONSTANTS}.key_enter and then login_button.is_sensitive then
				on_login
			end
		end

feature {NONE} -- User interface manipulation

	enable_login
			-- Enable login
		require
			is_initialized: is_initialized or is_initializing
			not_is_recycled: not is_recycled
			login_button_attached: login_button /= Void
			remember_me_check_attached: remember_me_check /= Void
		do
			if username_text.text.count >= 6 and then password_text.text.count >= 4 then
				login_button.enable_sensitive
				remember_me_check.enable_sensitive
			else
				login_button.disable_sensitive
				remember_me_check.disable_sensitive
			end
		end

	enable_login_content_widget (a_enable: BOOLEAN)
			-- Enable/disable login context wdigets based on login state
		require
			is_initialized: is_initialized or is_initializing
			not_is_recycled: not is_recycled
			login_frame_attached: login_frame /= Void
		do
			if a_enable then
				login_frame.disable_sensitive
				enable_report_frame_widgets

				if can_submit then
					dialog_window_buttons.item ({ES_DIALOG_BUTTONS}.ok_button).enable_sensitive
				else
					dialog_window_buttons.item ({ES_DIALOG_BUTTONS}.ok_button).disable_sensitive
				end
			else
				login_frame.enable_sensitive
				disable_report_frame_widgets

				dialog_window_buttons.item ({ES_DIALOG_BUTTONS}.ok_button).disable_sensitive
			end
		end

	disable_report_frame_widgets
			-- We want all widgets looks like disabled, so users can copy the title in the `synopsis_text' without login
			-- See bug#15066
		do
			-- FIXIT: We should fix {ES_COLORS}.disabled_foreground_color to REAL theme color
			report_frame.set_foreground_color (colors.disabled_foreground_color)

			synopsis_text.enable_sensitive
			synopsis_text.disable_edit
			synopsis_text.set_foreground_color (colors.disabled_foreground_color)

			description_text.disable_sensitive
			make_public_check.disable_sensitive
			severity_label.disable_sensitive
			severity_critical_radio.disable_sensitive
			severity_serious_radio.disable_sensitive
			severity_non_critical_radio.disable_sensitive
		end

	enable_report_frame_widgets
			-- Correspond to `disable_report_frame_widgets'
			-- We retore widgets' "sensitive" here
		local
			l_color: EV_STOCK_COLORS
		do
			create l_color

			report_frame.set_foreground_color (l_color.default_foreground_color)

			synopsis_text.enable_sensitive
			synopsis_text.enable_edit
			synopsis_text.set_foreground_color (l_color.default_foreground_color)

			description_text.enable_sensitive
			make_public_check.enable_sensitive
			severity_label.enable_sensitive
			severity_critical_radio.enable_sensitive
			severity_serious_radio.enable_sensitive
			severity_non_critical_radio.enable_sensitive
		end

feature {NONE} -- User interface elements

	login_frame: EV_FRAME
			-- Login container frame

	logged_in_label: EV_LABEL
			-- Logged in message label

	severity_label: EV_LABEL
				-- Severity label

	log_out_link: EV_LINK_LABEL
			-- Logged in message lable link to log ou

	username_text: EV_TEXT_FIELD
			-- Login username

	password_text: EV_PASSWORD_FIELD
			-- Login password

	remember_me_check: EV_CHECK_BUTTON
			-- Login remember me

	login_button: EV_BUTTON
			-- Login button

	report_frame: EV_FRAME
			-- Bug report container frame

	synopsis_text: EV_TEXT_FIELD
			-- Report synopsis

	description_text: EV_TEXT
			-- Report description

	make_public_check: EV_CHECK_BUTTON
			-- Report privacy option

	shrink_timer: EV_TIMEOUT
			-- Timer used to perform shrinking of login widgets

	shrink_interval: INTEGER = 3
			-- Default shink interval

	shrink_widget: EV_FIXED
			-- Shrink widget used to perform shinking

	severity_critical_radio: EV_RADIO_BUTTON
			-- Severity critical radio button

	severity_serious_radio: EV_RADIO_BUTTON
			-- Severity serious radio button

	severity_non_critical_radio: EV_RADIO_BUTTON
			-- Severity non-critical radio button

feature {NONE} -- Reporting

	synopsis: STRING_32
			-- Synopsis text
		require
			is_initialized: is_initialized or is_initializing
			not_is_recycled: not is_recycled
		local
			l_class_name: STRING
			l_recipient: STRING
			l_exceptions: EXCEPTIONS
			l_exception_tag: like {EXCEPTION}.tag
			l_exception_code: INTEGER_32
			l_description: like {EXCEPTION}.description
			l_exception: EXCEPTION
		do
			create Result.make (100)

			if not is_initialized or else not is_synopsis_available then
				create l_exceptions
				l_exception := l_exceptions.exception_manager.last_exception
				if l_exception /= Void then
					l_exception_tag := l_exception.original.tag
					l_exception_code := l_exception.original.code
				end
				if l_exception_tag = Void then
					l_exception_tag := {STRING_32} " " + l_exception_code.out + " Unknown exception code"
				end
				Result.append_string_general (l_exception_tag)
				Result.prune_all_trailing ('.')
				Result.append_character (' ')

				if l_exceptions.assertion_violation then
					Result.append ("Tag: ")
					if l_exception /= Void then
						l_description := l_exception.original.description
					end
					if l_description = Void then
						l_description := "unknown tag name"
					end
					Result.append_string_general (l_description)
					Result.append_character (' ')
				end

				if l_exception /= Void then
					l_class_name := l_exception.original.type_name
				end
				if l_class_name /= Void then
					Result.append ("in {")
					Result.append (l_class_name)
					Result.append_character ('}')
					l_recipient := l_exception.original.recipient_name
					if l_recipient /= Void then
						Result.append_character ('.')
						Result.append (l_recipient)
					end
				end
				Result.append (" in ")
				Result.append (workbench_name)
				Result.append_character ('.')
			else
				Result.append (synopsis_text.text)
			end
		ensure
			result_attached: Result /= Void
			not_result_is_empty: not Result.is_empty
		end

	description: STRING_32
			-- Description text
		require
			is_initialized: is_initialized or is_initializing
			not_is_recycled: not is_recycled
		local
			l_trace: STRING
			l_exceptions: EXCEPTIONS
		do
			create Result.make (512)
			if is_initialized and then is_description_available then
				Result.append (description_text.text)
				Result.prune_all_trailing ('%N')
				Result.append ("%N%N")
			end

			create l_exceptions
			l_trace := l_exceptions.exception_trace
			Result.append (l_trace)
		ensure
			result_attached: Result /= Void
			not_result_is_empty: not Result.is_empty
		end

	submit_bug_report
			-- Submits a bug report.
		require
			is_initialized: is_initialized
			not_is_recycled: not is_recycled
			support_login_is_logged_in: support_login.is_logged_in
		local
			l_report: ESA_SUPPORT_BUG_REPORT
			l_thanks: ES_INFORMATION_PROMPT
			l_error: ES_ERROR_PROMPT
			l_transistion: ES_POPUP_TRANSITION_WINDOW
			l_window: EV_WINDOW
			retried: BOOLEAN
		do
			if not retried then
				create l_transistion.make_with_icon (locale_formatter.translation (lb_submitting), stock_pixmaps.tool_output_failed_icon_buffer)
				l_window := dialog
				check l_window_attached: l_window /= Void end
				l_transistion.show_relative_to_window (l_window)

				create l_report.make (synopsis, description, compiler_version_number.version)
				l_report.environment := workbench_name + " " + version_number
				l_report.to_reproduce := "Please see description"
				l_report.confidential := not make_public_check.is_selected
				if severity_critical_radio.is_selected then
					l_report.severity := l_report.severity_critical
				elseif severity_non_critical_radio.is_selected then
					l_report.severity := l_report.severity_non_critical
				else
					check severity_serious_radio.is_selected end
					l_report.severity := l_report.severtiy_serious
				end

				support_login.report_bug (l_report)
				l_transistion.hide

				if support_login.is_bad_request then
					if attached support_login.last_error as ll_error then
						create l_error.make_standard ("Unable to submit bug report due to network problem. Please try again later.%N" + ll_error)
					else
						create l_error.make_standard ("Unable to submit bug report due to network problem. Please try again later.")
					end
					l_error.show (dialog)
				else
					create l_thanks.make_standard (locale_formatter.translation (lb_submitted))
					l_thanks.set_sub_title (locale_formatter.translation (tt_thank_you))
					l_thanks.show (dialog)
					is_submit_successed := True
				end
			else
				if attached l_transistion and then l_transistion.is_shown then
						-- Need to hide the transition window if there was a failure.
					l_transistion.hide
				end
				create l_error.make_standard (locale_formatter.translation (e_submit_error))
				l_error.show (dialog)
				is_submit_successed := False
					-- Do not close the submit dialog when error occurs
					-- this way the user can try again
				is_close_vetoed := True
			end
		rescue
			retried := True
			retry
		end

feature {NONE} -- Internationalization


	t_account_access: STRING = "Account Access"
	t_bug_information: STRING = "Bug Information"

	tt_thank_you: STRING = "Thank you for the bug report"

	lb_enter_bug_information: STRING = "Enter supplementary bug information"
	lb_enter_synopsis: STRING = "Enter synopsis"
	lb_make_public: STRING = "Make bug publicly available"
	lb_password: STRING = "Password:"
	lb_remember_me: STRING = "Remember me"
	lb_severity: STRING = "Severity:"
	lb_submitted: STRING
		once
			Result := "The submitted report is now available at "
			Result.append (support_url)
		end

	lb_submitting: STRING = "Submitting bug report, please wait..."
	lb_register_account: STRING = "If you do not already have an account, please register "
	lb_username: STRING = "Username:"

	b_here: STRING = "here"
	b_login: STRING = "Login"
	b_log_out: STRING = "Log out"
	b_submit: STRING = "Submit"

	i_critical: STRING = "Critical"
	i_serious: STRING = "Serious"
	i_non_critical: STRING = "Non Critical"

	w_no_description: STRING = "No bug description has been supplied. Submitting a report without additional details can make it hard to reproduce.%N%NDo you want to continue submitting a bug report?"
	e_submit_error: STRING
		once
			Result := "There was a problem submitting the problem report. Please retry or submit it manually at "
			Result.append (support_url)
		end

feature {NONE} -- Constants

	username_session_id: STRING_8 = "com.eiffel.exception_submit_dialog.username"
	password_session_id: STRING_8 = "com.eiffel.exception_submit_dialog.password"
	remembered_session_id: STRING_8 = "com.eiffel.exception_submit_dialog.remembered"


invariant
	support_reporter: support_login /= Void
	login_frame_attached: (is_initialized and not is_recycled) implies login_frame /= Void
	logged_in_label_attached: (is_initialized and not is_recycled) implies logged_in_label /= Void
	log_out_link_attached: (is_initialized and not is_recycled) implies log_out_link /= Void
	username_text_attached: (is_initialized and not is_recycled) implies username_text /= Void
	password_text_attached: (is_initialized and not is_recycled) implies password_text /= Void
	remember_me_check_attached: (is_initialized and not is_recycled) implies remember_me_check /= Void
	login_button_attached: (is_initialized and not is_recycled) implies login_button /= Void
	report_frame_attached: (is_initialized and not is_recycled) implies report_frame /= Void
	synopsis_text_attached: (is_initialized and not is_recycled) implies synopsis_text /= Void
	more_info_text_attached: (is_initialized and not is_recycled) implies description_text /= Void
	make_public_check_attached: (is_initialized and not is_recycled) implies make_public_check /= Void
	shrink_timer_attached: (is_initialized and not is_recycled) implies shrink_timer /= Void
	shrink_widget_attached: (is_initialized and not is_recycled) implies shrink_widget /= Void
	shrink_interval_positive: shrink_interval > 0

;note
	copyright: "Copyright (c) 1984-2020, Eiffel Software"
	license:   "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)"
	licensing_options: "http://www.eiffel.com/licensing"
	copying: "[
			This file is part of Eiffel Software's Eiffel Development Environment.
			
			Eiffel Software's Eiffel Development Environment is free
			software; you can redistribute it and/or modify it under
			the terms of the GNU General Public License as published
			by the Free Software Foundation, version 2 of the License
			(available at the URL listed under "license" above).
			
			Eiffel Software's Eiffel Development Environment is
			distributed in the hope that it will be useful, but
			WITHOUT ANY WARRANTY; without even the implied warranty
			of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
			See the GNU General Public License for more details.
			
			You should have received a copy of the GNU General Public
			License along with Eiffel Software's Eiffel Development
			Environment; if not, write to the Free Software Foundation,
			Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
		]"
	source: "[
			Eiffel Software
			5949 Hollister Ave., Goleta, CA 93117 USA
			Telephone 805-685-1006, Fax 805-685-6869
			Website http://www.eiffel.com
			Customer support http://support.eiffel.com
		]"

end