class MapPreview(object):
	"""Semiprivate class dealing with the map preview icon"""
	def __init__(self, get_widget):
		"""
		@param get_widget: returns the current widget (self.current)
		"""
		self.minimap = None
		self.calc_proc = None # handle to background calculation process
		self.get_widget = get_widget

	def update_map(self, map_file):
		"""Direct map preview update.
		Only use for existing maps, it's too slow for random maps"""
		if self.minimap is not None:
			self.minimap.end()
		world = self._load_raw_world(map_file)
		self.minimap = Minimap(self._get_map_preview_icon(),
			                     session=None,
			                     view=None,
			                     world=world,
			                     targetrenderer=horizons.main.fife.targetrenderer,
			                     imagemanager=horizons.main.fife.imagemanager,
			                     cam_border=False,
			                     use_rotation=False,
			                     tooltip=None,
			                     on_click=None,
			                     preview=True)
		self.minimap.draw()

	def update_random_map(self, map_params, on_click):
		"""Called when a random map parameter has changed.
		@param map_params: _get_random_map() output
		@param on_click: handler for clicks"""
		def check_calc_process():
			# checks up on calc process (see below)
			if self.calc_proc is not None:
				state = self.calc_proc.poll()
				if state is None: # not finished
					ExtScheduler().add_new_object(check_calc_process, self, 0.1)
				elif state != 0:
					self._set_map_preview_status(u"An unknown error occured while generating the map preview")
				else: # done

					data = open(self.calc_proc.output_filename, "r").read()
					os.unlink(self.calc_proc.output_filename)
					self.calc_proc = None

					icon = self._get_map_preview_icon()
					if icon is None:
						return # dialog already gone

					tooltip = _("Click to generate a different random map")

					if self.minimap is not None:
						self.minimap.end()
					self.minimap = Minimap(icon,
																 session=None,
																 view=None,
																 world=None,
																 targetrenderer=horizons.main.fife.targetrenderer,
																 imagemanager=horizons.main.fife.imagemanager,
																 cam_border=False,
																 use_rotation=False,
																 tooltip=tooltip,
																 on_click=on_click,
																 preview=True)
					self.minimap.draw_data( data )
					icon.show()
					self._set_map_preview_status(u"")

		if self.calc_proc is not None:
			self.calc_proc.kill() # process exists, therefore up is scheduled already
		else:
			ExtScheduler().add_new_object(check_calc_process, self, 0.5)

		# launch process in background to calculate minimap data
		minimap_icon = self._get_map_preview_icon()

		params =  json.dumps(((minimap_icon.width, minimap_icon.height), map_params))

		args = (sys.executable, sys.argv[0], "--generate-minimap", params)
		handle, outfilename = tempfile.mkstemp()
		os.close(handle)
		self.calc_proc = subprocess.Popen(args=args,
								                      stdout=open(outfilename, "w"))
		self.calc_proc.output_filename = outfilename # attach extra info
		self._set_map_preview_status(u"Generating preview...")


	@classmethod
	def generate_minimap(cls, size, parameters):
		"""Called as subprocess, calculates minimap data and passes it via string via stdout"""
		# called as standalone basically, so init everything we need
		from horizons.main import _create_main_db
		from horizons.entities import Entities
		from horizons.ext.dummy import Dummy
		db = _create_main_db()
		Entities.load_grounds(db, load_now=False) # create all references
		map_file = SingleplayerMenu._generate_random_map( parameters )
		world = cls._load_raw_world(map_file)
		location = Rect.init_from_topleft_and_size_tuples( (0, 0), size)
		minimap = Minimap(location,
											session=None,
											view=None,
											world=world,
											targetrenderer=Dummy(),
											imagemanager=Dummy(),
											cam_border=False,
											use_rotation=False,
											preview=True)
		# communicate via stdout
		print minimap.dump_data()

	@classmethod
	def _load_raw_world(cls, map_file):
		WorldObject.reset()
		world = World(session=None)
		world.inited = True
		world.load_raw_map( SavegameAccessor( map_file ), preview=True )
		return world

	def _get_map_preview_icon(self):
		"""Returns pychan icon for map preview"""
		return self.get_widget().findChild(name="map_preview_minimap")

	def _set_map_preview_status(self, text):
		"""Sets small status label next to map preview"""
		wdg = self.get_widget().findChild(name="map_preview_status_label")
		if wdg: # might show next dialog already
			wdg.text = text
class MapPreview(object):
    """Semiprivate class dealing with the map preview icon"""
    def __init__(self, get_widget):
        """
		@param get_widget: returns the current widget (self.current)
		"""
        self.minimap = None
        self.calc_proc = None  # handle to background calculation process
        self.get_widget = get_widget
        self._last_random_map_params = None

    def update_map(self, map_file):
        """Direct map preview update.
		Only use for existing maps, it's too slow for random maps"""
        if self.minimap is not None:
            self.minimap.end()
        world = self._load_raw_world(map_file)
        self.minimap = Minimap(
            self._get_map_preview_icon(),
            session=None,
            view=None,
            world=world,
            targetrenderer=horizons.globals.fife.targetrenderer,
            imagemanager=horizons.globals.fife.imagemanager,
            cam_border=False,
            use_rotation=False,
            tooltip=None,
            on_click=None,
            preview=True)
        self.minimap.draw()

    def update_random_map(self, map_params, on_click):
        """Called when a random map parameter has changed.
		@param map_params: _get_random_map() output
		@param on_click: handler for clicks"""
        if self._last_random_map_params == map_params:
            return  # we already display this, happens on spurious slider events such as hover
        self._last_random_map_params = map_params

        def check_calc_process():
            # checks up on calc process (see below)
            if self.calc_proc is not None:
                state = self.calc_proc.poll()
                if state is None:  # not finished
                    ExtScheduler().add_new_object(check_calc_process, self,
                                                  0.1)
                elif state != 0:
                    self._set_map_preview_status(
                        u"An unknown error occured while generating the map preview"
                    )
                else:  # done

                    data = open(self.calc_proc.output_filename, "r").read()
                    os.unlink(self.calc_proc.output_filename)
                    self.calc_proc = None

                    icon = self._get_map_preview_icon()
                    if icon is None:
                        return  # dialog already gone

                    tooltip = _("Click to generate a different random map")

                    if self.minimap is not None:
                        self.minimap.end()
                    self.minimap = Minimap(
                        icon,
                        session=None,
                        view=None,
                        world=None,
                        targetrenderer=horizons.globals.fife.targetrenderer,
                        imagemanager=horizons.globals.fife.imagemanager,
                        cam_border=False,
                        use_rotation=False,
                        tooltip=tooltip,
                        on_click=on_click,
                        preview=True)
                    self.minimap.draw_data(data)
                    icon.show()
                    self._set_map_preview_status(u"")

        if self.calc_proc is not None:
            self.calc_proc.kill(
            )  # process exists, therefore up is scheduled already
        else:
            ExtScheduler().add_new_object(check_calc_process, self, 0.5)

        # launch process in background to calculate minimap data
        minimap_icon = self._get_map_preview_icon()

        params = json.dumps(
            ((minimap_icon.width, minimap_icon.height), map_params))

        args = (sys.executable, sys.argv[0], "--generate-minimap", params)
        handle, outfilename = tempfile.mkstemp()
        os.close(handle)
        self.calc_proc = subprocess.Popen(args=args,
                                          stdout=open(outfilename, "w"))
        self.calc_proc.output_filename = outfilename  # attach extra info
        self._set_map_preview_status(u"Generating preview...")

    @classmethod
    def generate_minimap(cls, size, parameters):
        """Called as subprocess, calculates minimap data and passes it via string via stdout"""
        # called as standalone basically, so init everything we need
        from horizons.main import _create_main_db
        from horizons.entities import Entities
        from horizons.ext.dummy import Dummy
        db = _create_main_db()
        Entities.load_grounds(db, load_now=False)  # create all references
        map_file = SingleplayerMenu._generate_random_map(parameters)
        world = cls._load_raw_world(map_file)
        location = Rect.init_from_topleft_and_size_tuples((0, 0), size)
        minimap = Minimap(location,
                          session=None,
                          view=None,
                          world=world,
                          targetrenderer=Dummy(),
                          imagemanager=Dummy(),
                          cam_border=False,
                          use_rotation=False,
                          preview=True)
        # communicate via stdout
        print minimap.dump_data()

    @classmethod
    def _load_raw_world(cls, map_file):
        WorldObject.reset()
        world = World(session=None)
        world.inited = True
        world.load_raw_map(SavegameAccessor(map_file, True), preview=True)
        return world

    def _get_map_preview_icon(self):
        """Returns pychan icon for map preview"""
        return self.get_widget().findChild(name="map_preview_minimap")

    def _set_map_preview_status(self, text):
        """Sets small status label next to map preview"""
        wdg = self.get_widget().findChild(name="map_preview_status_label")
        if wdg:  # might show next dialog already
            wdg.text = text