note
	description: "[
		A {VIEW} that corresponds to the game board in Victory
		In the Pacific (VITP).  This view has widgets that hold
		and allow control of game actions (e.g. movement, attacks,
		repositions, etc) of game elements (e.g. ships, control
		markers, ports, etc.)
		]"
	author: "Jimmy J. Johnson"

class
	BOARD_VIEW

inherit

	VITP_CELL_VIEW
		redefine
			create_interface_objects,
			initialize,
			add_actions,
			set_target,
			draw,
			pick_notified_operations,
			pick_ended_operations
		end

	FONT_AND_COLOR_CONSTANTS
		export
			{NONE}
				all
		undefine
			default_create,
			copy
		end

	POSITION_CONSTANTS
		export
			{NONE}
				all
		undefine
			default_create,
			copy
		redefine
			playing_area_ratio
		end

create
	make

feature {NONE} -- Initialization

	create_interface_objects
			-- Create objects to be used by `Current' in `initialize'
			-- Implemented by descendants to create attached objects
			-- in order to adhere to void-safety due to the implementation bridge pattern.
		do
			print ("BOARD_VIEW.create_interface_objects %N")
			Precursor {VITP_CELL_VIEW}
			print ("%T BOARD_VIEW.create_interface_objects   before creating widget_factory %N")
			create widget_factory.make (game)
			print ("%T BOARD_VIEW.create_interface_objects   after creatingh widget_factory %N")
--			create dot
--			create bounding_figure
				-- Create for Void safety
--			create mouse_offset
			create last_mouse_position
				-- create containers
			create task_force_widgets.make (100)
			create highlighted_widgets.make
				-- create the corner points used to determine the scale factor
			create top_left_dot
			create bottom_right_dot
				-- create container for the grid cells (rows, columns)
--			create cell_array.make (playing_area_height // cell_size,

		end

	initialize
			-- Called after `Default_create'
		do
			Precursor {VITP_CELL_VIEW}
--			world.extend (dragging_arrow)
--			dragging_arrow.hide
--				-- create the `handle'
--			create handle
--			world.extend (handle)
			build_border
				-- Attack widgets go on top of all other widgets except the dots
--			build_corner_dots
				-- Place the dots from {POSITION_CONSTANTS} into Current
				-- The dots move based on scaling of the view, allowing
				-- cell positions to be determined regardless of the
				-- actual size of the view.
			add_widgets
			world.extend (top_left_dot)
			world.extend (bottom_right_dot)
		end

	add_widgets
			-- Add the sea areas, ports, and unit widgets to the `world',
			-- hiding the unit widgets until needed
		local
			wf: like widget_factory
			t: like widget_factory.widgets
			w: VITP_WIDGET
		do
			wf := widget_factory
				-- Add sea areas first
			t := wf.sea_area_widgets
			from t.start
			until t.after
			loop
--				world.extend (t.item_for_iteration)
				add_model (t.item_for_iteration)
				t.forth
			end
				-- Add ports
			t := wf.port_widgets
			from t.start
			until t.after
			loop
--				world.extend (t.item_for_iteration)
				add_model (t.item_for_iteration)
				t.forth
			end
				-- Add unit widgets	
			t := wf.attack_widgets
			from t.start
			until t.after
			loop
				w := t.item_for_iteration
				print ("{BOARD_VIEW}.add_widgets:  Adding " + w.target.name + " at (" + w.x.out + ", " + w.y.out + ") %N")
--				world.extend (w)
				add_model (w)
--				w.hide
				t.forth
			end
		end

	build_corner_dots
			-- Create the two dots that will mark the top-left and bottom-right corners of
			-- the board.  These aid calculation of the current scaling factor and scolling
		do
			top_left_dot.set_x_y (playing_area_left, playing_area_top)
			bottom_right_dot.set_x_y (playing_area_right, playing_area_bottom)
			top_left_dot.set_line_width (10)
			bottom_right_dot.set_line_width (10)
			world.extend (top_left_dot)
			world.extend (bottom_right_dot)
		end

	add_actions
			-- Add actions to the widgets
		local
			w: ATTACK_UNIT_WIDGET
		do
				-- Do not call precursor
--			asia_widget.pointer_button_press_actions.force_extend (agent toggle_land)
--			pointer_motion_actions.extend (agent on_pointer_moved)
--			pointer_button_release_actions.extend (agent on_button_released)
		end

	build_border
			-- Put a border around the game board to hide some of the land overhangs
		local
			poly: EV_MODEL_POLYGON
			s: INTEGER
			bw, bh: INTEGER_32
			c: EV_COLOR
		do
			s := 5
			c := Medium_grey
			bw := board_width
			bh := board_height
				-- top
			create poly.default_create
			poly.set_line_width (0)
			poly.extend_point (create {EV_COORDINATE}.make (-s, -s))
			poly.extend_point (create {EV_COORDINATE}.make (bw + s, -s))
			poly.extend_point (create {EV_COORDINATE}.make (bw + s, 0))
			poly.extend_point (create {EV_COORDINATE}.make (-s, 0))
			poly.set_background_color (c)
			poly.set_foreground_color (c)
			world.extend (poly)
				-- botton
			create poly.default_create
			poly.set_line_width (0)
			poly.extend_point (create {EV_COORDINATE}.make (-s, bh))
			poly.extend_point (create {EV_COORDINATE}.make (bw + s, bh))
			poly.extend_point (create {EV_COORDINATE}.make (bw + s, bh + s))
			poly.extend_point (create {EV_COORDINATE}.make (-s, bh + s))
			poly.set_background_color (c)
			poly.set_foreground_color (c)
			world.extend (poly)
				-- left
			create poly.default_create
			poly.set_line_width (0)
			poly.extend_point (create {EV_COORDINATE}.make (-s, -s))
			poly.extend_point (create {EV_COORDINATE}.make (0, -s))
			poly.extend_point (create {EV_COORDINATE}.make (0, bh + s))
			poly.extend_point (create {EV_COORDINATE}.make (-s, bh + s))
			poly.set_background_color (c)
			poly.set_foreground_color (c)
			world.extend (poly)
				-- right
			create poly.default_create
			poly.set_line_width (0)
			poly.extend_point (create {EV_COORDINATE}.make (bw, -s))
			poly.extend_point (create {EV_COORDINATE}.make (bw + s, -s))
			poly.extend_point (create {EV_COORDINATE}.make (bw + s, bh + s))
			poly.extend_point (create {EV_COORDINATE}.make (bw, bh + s))
			poly.set_background_color (c)
			poly.set_foreground_color (c)
			world.extend (poly)
		end

feature -- Basic operations

	set_target (a_item: like game)
			-- Associate `a_item' with Current.
		do
			Precursor (a_item)
				-- Build a polygon that defines the boundary of current for which we
				-- find the centerpoint, the `dot'.  Other widgets can then be built
				-- and if desired placed in Current relative to `dot'
			widget_factory.set_game (game)
--			paint
--			set_pebble (a_item)
--			set_accept_cursor (sub_pixmap (bounding_box))
		end

	draw
			-- Redraw the view
			-- This means the game has changed in some way
			-- (e.g. a ship was added).
		do
			if not is_view_empty then
--				update_attack_widgets
	-- should be no need to draw the whole view unless the game
	-- was changed.
			end
		end

feature -- Access

	widget_factory: ALL_WIDGETS_FACTORY
		-- Holds all the widgets on the board

	playing_area_ratio: REAL_64
			-- Ratio of the playing_area_width' to the [possibly]
			-- scaled size of the `playing_area_width'.  Default = one,
			-- but redefined here to use the distance between the
			-- two corner dots.
		do
			Result := playing_area_width / (bottom_right_dot.x - top_left_dot.x)
		end

feature -- Query

	cell_at (a_x, a_y: INTEGER_32): VITP_CELL
			-- The cell at the screen coordinates `a_x', `a_y'
		local
			x, y: INTEGER_32
		do
			x := ((a_x * playing_area_ratio) / cell_size).truncated_to_integer + 1
			y := ((a_y * playing_area_ratio) / cell_size).truncated_to_integer + 1
			Result := game.cell (x, y)
		end

	screen_coordinates (a_cell: VITP_CELL): TUPLE [x, y: INTEGER_32]
			-- The screen coordinates corresponding to `a_cell'
		local
			x, y: INTEGER_32
		do
			x := ((a_cell.index.x * cell_size) / playing_area_ratio).truncated_to_integer
			y := ((a_cell.index.y * cell_size) / playing_area_ratio).truncated_to_integer
			Result := [x, y]
		end

feature -- Status report

	is_forwarding: BOOLEAN
			-- Has a widget been brought to the top?

	is_dragging: BOOLEAN
			-- Are we in the process of sliding a widget or a group of widgets?

--	is_picking: BOOLEAN
--			-- Are we in the process of a pick-and-put operation?

	is_repositioning: BOOLEAN
			-- Is a widget being repositioned?

	is_moving: BOOLEAN
			-- Is a unit being moved to a new location?

	is_highlighting: BOOLEAN
			-- Is a widget or group of widgets being emphasized?

	is_highlighting_location: BOOLEAN
			-- Is one or more port widgets being emphasized?

	is_highlighting_units: BOOLEAN
			-- Is one or more unit widgets being emphasized?

	is_highlighting_task_force: BOOLEAN
			-- Is one or more {TASK_FORCE_WIDGET}s being emphasized?

	is_processing_task_force: BOOLEAN
			-- A {TASK_FORCE_WIDGET} is being clicked/move/released

feature -- Actions

	pick_notified_operations (a_target: ANY)
			-- React to the pick of `a_target' from some view
		local
			sop: like game.sequence_of_play
			set: LINKED_SET [PORT]
			p: PORT
			pw: PORT_WIDGET
		do
			Precursor (a_target)
			print ("{BOARD_VIEW}.pick_notified_operations on {" + generating_type.name + "}%N")
			sop := game.sequence_of_play
			if sop.is_reinforcement_step and then attached {ATTACK_UNIT} a_target as t then
				set := t.reinforceable_ports
				print ("%T undimming  " + set.count.out + "  areas %N")
				from set.start
				until set.after
				loop
					p := set.item
					print ("%T%T making  " + p.name + "  brighter %N")
					pw := widget_factory.port_widgets.definite_item (p)
					pw.set_dimming_level ({DIMABLE}.bright)
					pw.activate_drop_action
					highlighted_widgets.extend (pw)
					set.forth
				end
	--			application.process_graphical_events
			end
		end

	pick_ended_operations
			-- React to the end of a pick and drop operation
		do
			Precursor
			print ("{BOARD_VIEW}.pick_ended_operations on {" + generating_type.name + "} %N")
			from highlighted_widgets.start
			until highlighted_widgets.after
			loop
				highlighted_widgets.item.deactivate_drop_action
				highlighted_widgets.item.restore_dimming_level
				highlighted_widgets.forth
			end
			highlighted_widgets.wipe_out
		end

	on_pointer_enter (a_widget: VITP_WIDGET)
			-- React to a pointer entering `a_widget'
		local
			tfw: TASK_FORCE_WIDGET
		do
			io.put_string ("BOARD_WORLD.on_pointer_enter:  on " + a_widget.target.name + " %N")
--			if attached {ATTACK_UNIT_WIDGET} a_widget as w then
--				if w.unit.is_task_force then
--					tfw := task_force_widgets.widget (w.unit.task_force)
--					forward_widget_to_top (w, tfw)
--				end
--			end
		end

	on_pointer_leave (a_widget: VITP_WIDGET)
			-- React to a pointer leaving a `a_widget'
		do
			io.put_string ("BOARD_WORLD.on_pointer_leave:  on " + a_widget.target.name + " %N")
--			if is_forwarding then
--				restore_forwarded_widget
--			end
		end

	on_button_pressed (a_widget: VITP_WIDGET; ax: INTEGER; ay: INTEGER; a_button: INTEGER)
			-- React to a pointer button pressed notification from `a_widget'
		do
			io.put_string ("BOARD_WORLD.on_button_pressed:  button " + a_button.out +
							" pressed at (" + ax.out + ", " + ay.out + ") on " + a_widget.target.name + " %N")
--			last_mouse_position.set_precise (ax, ay)
--			if is_forwarding then
--				restore_forwarded_widget
--			end
--			if a_button = 1 then
--				if attached {ATTACK_UNIT_WIDGET} a_widget as w then
--					highlight_unit (w.unit)
--					begin_widget_reposition (w, ax, ay)
--				elseif attached {LOCATION_WIDGET} a_widget as w then
--					highlight_location (w.location)
--					highlight_location_occupants (w.location)
--				end
--			end
		end

	on_button_double_pressed (a_widget: VITP_WIDGET; ax: INTEGER; ay: INTEGER; a_button: INTEGER)
			-- React to a pointer button released notification from `a_widget'
		do
			io.put_string ("BOARD_WORLD.on_button_double_pressed:  button " + a_button.out +
							" double-pressed at (" + ax.out + ", " + ay.out + ") on " + a_widget.target.name + "%N")
			if a_button = 1 then
				if attached {TASK_FORCE_WIDGET} a_widget as w and then
							not w.point_on_bounding_figure (ax, ay) then
					if w.is_stacked then
						w.tile
					else
						w.stack
					end
						-- Next lines to prevent undesired movement
					is_repositioning := false
				end
			end
		end

	on_button_released (a_widget: VITP_WIDGET; ax: INTEGER; ay: INTEGER; a_button: INTEGER)
			-- React to a pointer button released notification from `a_widget'
		do
			io.put_string ("BOARD_WORLD.on_button_released:  button " + a_button.out + " pressed at (" + ax.out + ", " + ay.out + ") %N")
			if is_highlighting_location then
				normalize_locations
			end
			if is_highlighting_units then
				normalize_units
			end
			if is_repositioning then
--				finish_widget_reposition
			end
		end

	on_pointer_motion (a_widget: VITP_WIDGET; ax, ay: INTEGER)
			-- React to a pointer move notification from `a_widget'
		do
			io.put_string ("BOARD_WORLD.on_notify_pointer_motion:  at (" + ax.out + ", " + ay.out + ") %N")
--			if is_repositioning then
----				last_mouse_position.set_position (ax, ay)
--					-- Adjust for difference in the location of `active_widget' and `last_mouse_position'
----				if can_reposition (ax, ay) then
----					set_pointer_style (create {EV_POINTER_STYLE}.make_predefined ({EV_POINTER_STYLE_CONSTANTS}.Standard_cursor))
----					reposition_active_widget (ax, ay)
----				else
----					set_pointer_style (create {EV_POINTER_STYLE}.make_predefined ({EV_POINTER_STYLE_CONSTANTS}.No_cursor))
----				end
--			end
		end

feature -- Basic operations

	position_task_force_widget (a_widget: TASK_FORCE_WIDGET)
			-- Place `a_widget' on the board so it does not overlap other
			-- widgets, possibly moving other widgets.
		do

		end

	position_widget (a_widget: ATTACK_UNIT_WIDGET)
			-- Ensure each widget is postioned according to its position,
			-- perhaps repositioning it to accomodate other widgets.
		do

		end

feature --{WIDGET_FACTORY} -- Basic operations

	on_flip_widget (a_widget: SHIP_WIDGET)
			-- Toggle the raiding status of `a_widget'
		do
			io.put_string ("on_flip_raider /n")
			a_widget.flip
		ensure
			ship_status_toggled: a_widget.ship.is_raiding = not (old a_widget.ship.is_raiding)
		end

	board_coordinate_to_model_position (a_position: EV_COORDINATE): VITP_POSITION
			-- `a_position' converted to the model's coordinate system
		require
			position_exists: a_position /= Void
		local
			brp, tlp: EV_COORDINATE
			p: EV_COORDINATE
			x_size, y_size: REAL_64
			long, lat: REAL_64
		do
			p := a_position
			brp := bottom_right_dot.point
			tlp := top_left_dot.point
			x_size := brp.x_precise - tlp.x_precise
			y_size := brp.y_precise - tlp.y_precise
			long := (p.x_precise - tlp.x_precise) * (board_right / x_size)
			lat := (p.y_precise - tlp.y_precise) * (board_bottom / y_size)
			create Result.set_xy (long.truncated_to_integer, lat.truncated_to_integer)
		end

	highlight_location (a_location: LOCATION)
			-- Brighten the widget corresponding to `a_location'
		require
			location_exists: a_location /= Void
		local
			w: VITP_WIDGET
		do
			w := widget_factory.widgets.definite_item (a_location)
			if world.has (w) then
				w.set_dimming_level ({DIMABLE}.Bright)
				w.paint
				highlighted_widgets.extend (w)
				is_highlighting_location := true
			end
		end

	highlight_location_occupants (a_location: LOCATION)
			-- Brighten the widgets corresponding to the occupants of `a_location'
		require
			location_exists: a_location /= Void
		local
			u_list: LINKED_SET [ATTACK_UNIT]
			w: VITP_WIDGET
		do
			u_list := a_location.units
			from u_list.start
			until u_list.after
			loop
				w := widget_factory.widgets.definite_item (u_list.item)
				w.set_dimming_level ({DIMABLE}.Bright)
				w.paint
				highlighted_widgets.extend (w)
				u_list.forth
			end
			is_highlighting_units := true
		end

	highlight_unit (a_unit: ATTACK_UNIT)
			-- Brighten the widget corresponding to `a_unit'
		require
			unit_exists: a_unit /= Void
		local
			tfw: TASK_FORCE_WIDGET
			w: VITP_WIDGET
		do
--			if a_unit.is_task_force then
--				tfw := task_force_widgets.widget (a_unit.task_force)
--				if tfw.is_stacked then
--					w := tfw
--				else
--					w := world.attack_widgets.widget (a_unit)
--				end
--			else
--				w := world.attack_widgets.widget (a_unit)
--			end
			w := widget_factory.widgets.definite_item (a_unit)
			w.set_dimming_level ({DIMABLE}.Bright)
			w.paint
			highlighted_widgets.extend (w)
			is_highlighting_units := true
		end

	normalize_locations
			-- Restor all location widgets to a normal brightness level
		local
			w: LOCATION_WIDGET
		do
--			from world.location_widgets.start
--			until world.location_widgets.after
--			loop
--				w := world.location_widgets.item_for_iteration
--				w.set_dimming_level ({DIMABLE}.Normal)
--				w.paint
--				world.location_widgets.forth
--			end
--			is_highlighting_location := false
		end

	normalize_units
			-- Restore all attack widgets to a normal brightness level
		local
			w: ATTACK_UNIT_WIDGET
		do
--			from world.attack_widgets.start
--			until world.attack_widgets.after
--			loop
--				w := world.attack_widgets.item_for_iteration
--				w.set_dimming_level ({DIMABLE}.Normal)
--				w.paint
--				world.attack_widgets.forth
--			end
--			is_highlighting_units := false
		end

feature --{VITP_WIDGET} -- Implementation

	task_force_widgets: VITP_WIDGET_TABLE [TASK_FORCE_WIDGET, TASK_FORCE]

	last_mouse_position: EV_COORDINATE
			-- For possible restoration to the location where the reposition began

	forwarded_widget: detachable ATTACK_UNIT_WIDGET
			-- A widget that has been brought to the top of its owner

	forwarded_widget_owner: detachable VITP_WIDGET
			-- The widget in which `forwarded_widget' resides

	highlighted_widgets: LINKED_SET [VITP_WIDGET]
			-- The widgets with the focus

	top_left_dot: EV_MODEL_DOT
			-- A dot at top left of the board, that will scale and scroll with the view,
			-- whose position when compared with `bottom_right_dot' provides a scale
			-- factor used to position widgets

	bottom_right_dot: EV_MODEL_DOT
			-- See `top_left_dot'

feature {NONE} -- Implementation

--	X_stacking_increment: INTEGER
--			-- The distance in pixels to offset a stacked widget in the x direction
--		local
--			w: ATTACK_UNIT_WIDGET
--		do
--				-- Since we base this distance on the current size of a ship widget,
--				-- we must ensure we have a widget from which to calculate the value.
--			check not world.attack_widgets.is_empty then
--				w := world.attack_widgets.iteration_item (1)
----				Result := (w.tile_size / 10).rounded
--				Result := (w.tile_size / 10).rounded
--			end
--		end

--	Y_stacking_increment: INTEGER
--			-- The distance in pixels to offset a stacked widget in the x direction
--		local
--			w: ATTACK_UNIT_WIDGET
--		do
--				-- Since we base this distance on the current size of a ship widget,
--				-- we must ensure we have a widget from which to calculate the value.
--			check not world.attack_widgets.is_empty then
--				w := world.attack_widgets.iteration_item (1)
----				Result := (w.tile_size / 10).rounded
--				Result := (w.tile_size / 10).rounded
--			end
--		end


--feature {NONE} -- Implemetation

--	target_imp: detachable VITP_GAME
--			-- Detachable implementation of `target' for void safety

end
