# coding:utf-8

import glob
import os.path
import urllib

import pkg_resources
import wx

import cellprofiler
import cellprofiler.gui.help.content
import cellprofiler.gui.html
import cellprofiler.gui.html.utils
import cellprofiler.preferences

CONFIGURE_IMAGES_REF = urllib.quote("Configure images")
EXPORTING_RESULTS_REF = urllib.quote("Exporting results")
IDENTIFY_FEATUREES_REF = urllib.quote("Identifying features")
IN_APP_HELP_REF = urllib.quote("Using the help")
MAKING_MEASUREMENTS_REF = urllib.quote("Making measurements")
RUNNING_YOUR_PIPELINE_REF = urllib.quote("Analyzing your images")
TEST_MODE_REF = urllib.quote("Using test mode")
SELECTING_IMAGES_REF = urllib.quote("Selecting images")
WELCOME_MAIN_REF = urllib.quote("Welcome")

GO_BACK = """<p>Go <a href=help://{}>back</a> to the welcome screen.</p>""".format(WELCOME_MAIN_REF)

CONFIGURE_IMAGES_HELP = u"""\
<!DOCTYPE html>
<html>
<head>
    <title>Configure images</title>
</head>
<body>
    {CONFIGURE_IMAGES_CONTENT}
    {GO_BACK}
</body>
""".format(**{
    "GO_BACK": GO_BACK,
    "CONFIGURE_IMAGES_CONTENT": cellprofiler.gui.html.utils.rst_to_html_fragment(
        cellprofiler.gui.help.content.read_content("projects_configure_images.rst")
    )
})

EXPORTING_RESULTS_HELP = u"""\
<!DOCTYPE html>
<html>
<head>
    <title>Exporting results</title>
</head>
<body>
    <p>Writing the measurements generated by CellProfiler is necessary for
    downstream statistical analysis. The most common format for export is the
    <i>spreadsheet</i> which is a table of values. The module
    <b>ExportToSpreadsheet</b> handles the task of writing the measurements
    (for images, objects or both) to a file readable by Excel, or the
    spreadsheet program of your choice.</p>
    <p>For larger assays, involving tens of thousands of images or more, a
    spreadsheet is usually insufficient to handle the massive amounts of data
    generated. A <i>database</i> is a better solution in this case, although
    this requires more computational expertise; the <b>ExportToDatabase</b>
    module is to be used for this task. If this avenue is needed, it is best to
    consult with your information technology department.</p>
    <p>CellProfiler will not save images produce by analysis modules unless
    told to do so. It is often desirable to save the outlines of the objects
    identified; this can is useful as a sanity check of the object
    identification results or for quality control purposes. The
    <b>SaveImages</b> module is used for saving images to a variety of output
    formats; you can specify the nomenclature.</p>
    <p>For more information on these modules and how to configure them for best
    performance, please see the detailed help by selecting the module and
    clicking the <img src="{MODULE_HELP_BUTTON}"> button at the bottom
    of the pipeline panel. You can also find details on various exporting
    options under <i>{USING_YOUR_OUTPUT_REF}</i></p>
    {GO_BACK}
</body>
</html>
""".format(**{
    "GO_BACK": GO_BACK,
    "MODULE_HELP_BUTTON": cellprofiler.gui.help.content.MODULE_HELP_BUTTON,
    "USING_YOUR_OUTPUT_REF": cellprofiler.gui.help.content.USING_YOUR_OUTPUT_REF
})

IDENTIFY_FEATUREES_HELP = u"""\
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <p>A hallmark of most CellProfiler pipelines is the identification of
    cellular features in your images, whether they are nuclei, organelles or
    something else.</p>
    <table cellpadding="0" width="75%">
        <tr>
            <td valign="top" width="75%">A number of modules are dedicated to
            the purpose of detecting these features; the
            <b>IdentifyPrimaryObjects</b> module is the one that is most
            commonly used. The result of this module is a set of labeled
            <i>objects</i>; we define an object as a collection of connected
            pixels in an image which share the same label. The challenge here
            is to find a combination of settings that best identify the objects
            from the image, a task called <i>segmentation</i>. The typical
            expectation is to end up with one object for each cellular feature
            of interest (for example, each nucleus is assigned to a single
            object in a DNA stained image). If this is not the case, the module
            settings can be adjusted to make it so (or as close as possible).
            In some cases, image processing modules must be used beforehand to
            transform the image so it is more amenable to object
            detection.</td>
            <td align="center" width="25%"><img height="225" src=
            "memory:image_to_object_dataflow.png" width="254"></td>
        </tr>
    </table>
    <p>In brief, the workflow of finding objects using this module is to do the
    following:</p>
    <ul>
        <li><i>Distinguish the foreground from background:</i> The foreground
        is defined as that part of the image which contains the features of
        interest, as opposed to the <i>background</i> which does not. The
        module assumes that the foreground is brighter than the background,
        which is the case for fluorescence images; for other types of images,
        other modules can be used to first invert the image, turning dark
        regions into bright regions and vice versa.</li>
        <li><i>Identify the objects in each foreground region:</i> Each
        foreground region may contain multiple objects of interest (for
        example, touching nuclei in a DNA stained image). Recognizing the
        presence of these objects is the objective of this step.</li>
        <li><i>Splitting clusters of objects:</i> If objects are touching each
        other, the final step is to separate them in a way that reflects the
        actual boundaries as much as possible. This process is referred to as
        "declumping."</li>
    </ul>The module also contains additional settings for filtering the results
    of this process on the basis of size, location, etc. to get the final
    object set. At this point, the objects are ready for measurements to be
    made, or for further manipulations as a means of extracting other features.
    <p></p>
    <p>Other modules are able to take the results of this module and use them
    in combination with additional images (like
    <b>IdentifySecondaryObjects</b>) or other objects (like
    <b>IdentifyTertiaryObjects</b>) to define yet more objects.</p>
    <p>For more information on these identification modules work and how to
    configure them for best performance, please see the detailed help by
    selecting the <b>IdentifyPrimaryObjects</b> module and clicking the
    <img src="{MODULE_HELP_BUTTON}">&nbsp; button at the bottom of the
    pipeline panel.</p>
    {GO_BACK}
</body>
</html>
""".format(**{
    "GO_BACK": GO_BACK,
    "MODULE_HELP_BUTTON": cellprofiler.gui.help.content.MODULE_HELP_BUTTON
})

IN_APP_HELP = u"""\
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <p>In addition to the Help menu in the main CellProfiler window, there are <img src="{MODULE_HELP_BUTTON}">
    buttons containing more specific documentation for using CellProfiler. Clicking the "?" button near the pipeline 
    window will show information about the selected module within the pipeline, whereas clicking the 
    <img src="{MODULE_HELP_BUTTON}"> button to the right of each of the module setting displays help for that 
    particular setting.</p>
    {GO_BACK}
</body>
</html>
""".format(**{
    "GO_BACK": GO_BACK,
    "MODULE_HELP_BUTTON": cellprofiler.gui.help.content.MODULE_HELP_BUTTON
})

MAKING_MEASUREMENTS_HELP = u"""\
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <p>In most cases, the reason for identifying image features is to make
    measurements on them. CellProfiler has a number of modules dedicated to
    calculating measurements of various types, on both images and objects;
    these are accessible by clicking the <img src=
    "{MODULE_ADD_BUTTON}">&nbsp;button (located underneath the pipeline
    panel)</p>
    <p>Below is a list of measurement categories; these is not meant to be
    comprehensive, but are sufficient for most assays:</p>
    <table border="1" cellpadding="10">
        <tr align="center" bgcolor="#555555">
            <th><font color="#FFFFFF"><b>Measurement</b></font></th>
            <th><font color="#FFFFFF"><b>Description</b></font></th>
            <th><font color="#FFFFFF"><b>Relevant modules</b></font></th>
        </tr>
        <tr align="center">
            <td><i>Count</i></td>
            <td>The number of objects in an image.</td>
            <td>All modules which produce a new set of objects, such as
            <b>IdentifyPrimaryObjects</b></td>
        </tr>
        <tr align="center">
            <td><i>Location</i></td>
            <td>The (x,y) coordinates of each object, which can be of interest
            in time-lapse imaging.</td>
            <td>All modules which produce a new set of objects</td>
        </tr>
        <tr align="center">
            <td><i>Morphology</i></td>
            <td>Quantities defining the geometry of the object, as defined by
            its external boundary. This includes quantities like area,
            perimeter, etc.</td>
            <td>
            <b>MeasureImageAreaOccupied</b>,<b>MeasureObjectSizeShape</b></td>
        </tr>
        <tr align="center">
            <td><i>Intensity</i></td>
            <td>In fluorescence assays, the intensity of a pixel is related to
            the substance labeled with a fluorescence marker at that location.
            The maximal, minimal, mean, and integrated (total) intensity of
            each marker can be measured as well as correlations in intensity
            between channels.</td>
            <td><b>MeasureObjectIntensity</b>, <b>MeasureImageIntensity</b>,
            <b>MeasureObjectRadialDistribution</b>,
            <b>MeasureColocalization</b></td>
        </tr>
        <tr align="center">
            <td><i>Texture</i></td>
            <td>These quantities characterize spatial smoothness and regularity
            across an object, and are often useful for characterizing the fine
            patterns of localization.</td>
            <td><b>MeasureTexture</b></td>
        </tr>
        <tr align="center">
            <td><i>Clustering</i></td>
            <td>Spatial relationships can be characterized by adjacency
            descriptors, such as the number of neighboring objects, the percent
            of the perimeter touching neighbor objects, etc.</td>
            <td><b>MeasureObjectNeighbors</b></td>
        </tr>
    </table>
    <p>For more information on these modules and how to configure them for best
    performance, please see the detailed help by selecting the module and
    clicking the <img src="{MODULE_HELP_BUTTON}">&nbsp; button at the bottom of
    the pipeline panel. You can also find details on measurement nomenclature
    when exporting under <i>{MEASUREMENT_NAMING_HELP}</i></p>
    {GO_BACK}
</body>
</html>
""".format(**{
    "GO_BACK": GO_BACK,
    "MEASUREMENT_NAMING_HELP": cellprofiler.gui.help.content.MEASUREMENT_NAMING_HELP,
    "MODULE_ADD_BUTTON": cellprofiler.gui.help.content.MODULE_ADD_BUTTON,
    "MODULE_HELP_BUTTON": cellprofiler.gui.help.content.MODULE_HELP_BUTTON
})

RUNNING_YOUR_PIPELINE_HELP = u"""\
<!DOCTYPE html>
<html>
<head>
    <title>Analyzing your images</title>
</head>
<body>
    {RUNNING_YOUR_PIPELINE_CONTENT}
    {GO_BACK}
</body>
""".format(**{
    "GO_BACK": GO_BACK,
    "RUNNING_YOUR_PIPELINE_CONTENT": cellprofiler.gui.html.utils.rst_to_html_fragment(
        cellprofiler.gui.help.content.read_content("pipelines_running.rst")
    )
})

TEST_MODE_HELP = u"""\
<!DOCTYPE html>
<html>
<head>
    <title>Using test mode</title>
</head>
<body>
    {TEST_MODE_CONTENT}
    {GO_BACK}
</body>
""".format(**{
    "GO_BACK": GO_BACK,
    "TEST_MODE_CONTENT": cellprofiler.gui.html.utils.rst_to_html_fragment(
        cellprofiler.gui.help.content.read_content("navigation_test_menu.rst")
    )
})

SELECTING_IMAGES_HELP = u"""\
<!DOCTYPE html>
<html>
<head>
    <title>Selecting images</title>
</head>
<body>
    {SELECTING_IMAGES_CONTENT}
    {GO_BACK}
</body>
""".format(**{
    "GO_BACK": GO_BACK,
    "SELECTING_IMAGES_CONTENT": cellprofiler.gui.html.utils.rst_to_html_fragment(
        cellprofiler.gui.help.content.read_content("projects_selecting_images.rst")
    )
})

WELCOME_MAIN = u"""\
<!DOCTYPE html>
<html>
<head>
    <title></title>
</head>
<body>
    <table border="0" cellpadding="4" width="100%">
        <tr>
            <td align="center" colspan="3"><b><font size="+3">Welcome to
            CellProfiler!</font></b></td>
        </tr>
        <tr>
            <td colspan="3">CellProfiler is automated image analysis software
            to measure biological phenotypes in images.</td>
        </tr>
        <tr>
            <td colspan="3"><b><font size="+2">See a pipeline in
            action</font></b></td>
        </tr>
        <tr>
            <td width="1">&nbsp;</td>
            <td colspan="2">
                <a href=
                "loadexample:ExampleFly">
                Load</a> an example pipeline, then click on the "Analyze
                Images" button.
            </td>
        </tr>
        <tr>
            <td colspan="3"><b><font size="+2">Build your own
            pipeline</font></b></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td width="100"><font size="+2">1: Start</font></td>
            <td>
                <a href=
                "http://www.cellprofiler.org/examples.html">Download</a> a
                pipeline template from our website of examples. Load it with
                <i>File &gt; Import &gt; Pipeline from File...</i>. Run it,
                then modify it to suit your assay.
            </td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><i><font size="+2">2: Adjust</font></i></td>
            <td>
                Use the Input modules to <a href=
                "help://{SELECTING_IMAGES_REF}">select</a> and <a href=
                "help://{CONFIGURE_IMAGES_REF}">configure</a> your images for
                analysis. Add Analysis modules to <a href=
                "help://{IDENTIFY_FEATUREES_REF}">identify</a> image features,
                make <a href=
                "help://{MAKING_MEASUREMENTS_REF}">measurements</a> and
                <a href="help://{EXPORTING_RESULTS_REF}">export</a> results.
            </td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><i><font size="+2">3: Test</font></i></td>
            <td>
                Click the "Start Test Mode" button to step through the pipeline
                and <a href="help://{TEST_MODE_REF}">check</a> the module
                settings on a few images.
            </td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td><i><font size="+2">4: Analyze</font></i></td>
            <td>
                Click the "Analyze Images" button to <a href=
                "help://{RUNNING_YOUR_PIPELINE_REF}">process</a> all of your
                images with your pipeline.
            </td>
        </tr>
    </table><br>
    <table>
        <tr>
            <td colspan="3"><b><font size="+2">Need more help?</font></b></td>
        </tr>
        <tr>
            <td>&nbsp;</td>
            <td colspan="2">
                <table border="5" cellpadding="5" cellspacing="5">
                    <tr>
                        <td align="center" width="100">
                            <b><font size="+1">In-App Help</font></b><br>
                            <br>
                            <a href="help://{IN_APP_HELP_REF}"><img src=
                            "memory:welcome_screen_help.png"></a><br>
                            <br>
                            Click <b>?</b> buttons for detailed help
                        </td>
                        <td align="center" width="100">
                            <b><font size="+1">Manual</font></b><br>
                            <br>
                            <a href=
                            "{MANUAL_URL}">
                            <img src="memory:welcomescreen_manual.png"></a><br>
                            <br>
                            Online version of In-App help
                        </td>
                        <td align="center" width="100">
                            <b><font size="+1">Tutorials/Demos</font></b><br>
                            <br>
                            <a href=
                            "http://cellprofiler.org/tutorials.html"><img src=
                            "memory:welcomescreen_tutorials.png"></a><br>
                            <br>
                            For written and video guidance to image analysis
                        </td>
                        <td align="center" width="100">
                            <b><font size="+1">Q&A Forum</font></b><br>
                            <br>
                            <a href="http://forum.cellprofiler.org/"><img src=
                            "memory:welcomescreen_forum.png"></a><br>
                            <br>
                            Post a question online
                        </td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
    <p>Click <a href="pref:no_display">here</a> to stop displaying this page
    when CellProfiler starts. This page can be accessed from <i>Help &gt; Show
    Welcome Screen</i> at any time.</p>
</body>
</html>
""".format(**{
    "CONFIGURE_IMAGES_REF": CONFIGURE_IMAGES_REF,
    "EXPORTING_RESULTS_REF": EXPORTING_RESULTS_REF,
    "IDENTIFY_FEATUREES_REF": IDENTIFY_FEATUREES_REF,
    "IN_APP_HELP_REF": IN_APP_HELP_REF,
    "MAKING_MEASUREMENTS_REF": MAKING_MEASUREMENTS_REF,
    "MANUAL_URL": cellprofiler.gui.help.content.MANUAL_URL,
    "RUNNING_YOUR_PIPELINE_REF": RUNNING_YOUR_PIPELINE_REF,
    "SELECTING_IMAGES_REF": SELECTING_IMAGES_REF,
    "TEST_MODE_REF": TEST_MODE_REF
})


class Welcome(wx.Frame):
    def __init__(self, parent):
        super(Welcome, self).__init__(
            parent,
            name="WelcomeScreenFrame",
            size=(640, 480),
            title="Welcome to CellProfiler",
        )

        self.Sizer = wx.BoxSizer()

        self.SetIcon(cellprofiler.gui.get_cp_icon())

        self.Bind(wx.EVT_CLOSE, self.__on_close)

        self.content = Content(self)

        self.content.SetPage(WELCOME_MAIN)

        self.Sizer.Add(self.content, 1, wx.EXPAND)

        self.Layout()

    @staticmethod
    def __on_close(event):
        event.EventObject.Hide()

        event.Veto()


class Content(cellprofiler.gui.html.htmlwindow.HtmlClickableWindow):
    href_to_help = {
        CONFIGURE_IMAGES_REF: CONFIGURE_IMAGES_HELP,
        EXPORTING_RESULTS_REF: EXPORTING_RESULTS_HELP,
        IDENTIFY_FEATUREES_REF: IDENTIFY_FEATUREES_HELP,
        IN_APP_HELP_REF: IN_APP_HELP,
        MAKING_MEASUREMENTS_REF: MAKING_MEASUREMENTS_HELP,
        RUNNING_YOUR_PIPELINE_REF: RUNNING_YOUR_PIPELINE_HELP,
        TEST_MODE_REF: TEST_MODE_HELP,
        SELECTING_IMAGES_REF: SELECTING_IMAGES_HELP,
        WELCOME_MAIN_REF: WELCOME_MAIN
    }

    def __init__(self, parent):
        super(Content, self).__init__(parent)

    def OnLinkClicked(self, linkinfo):
        href = linkinfo.Href

        if href.startswith("help:"):
            self.__display_help(href[7:])
        elif href.startswith("loadexample:"):
            self.__load_example_pipeline(href[12:])
        elif href.startswith("pref:"):
            self.__set_startup_blurb()
        else:
            super(Content, self).OnLinkClicked(linkinfo)

    def __display_help(self, href):
        html_str = self.href_to_help[href]
        self.SetPage(html_str)

    @staticmethod
    def __load_example_pipeline(example_name):
        example_dir = pkg_resources.resource_filename(
            "cellprofiler",
            os.path.join("data", "examples", example_name)
        )

        pipeline_pathname = os.path.join(example_dir, "{:s}.cppipe".format(example_name))

        images_dir = os.path.join(example_dir, "images")

        try:
            def load(pathname=pipeline_pathname):
                pipeline = wx.GetApp().frame.pipeline
                pipeline.load(pathname)
                pipeline.add_pathnames_to_file_list(glob.glob(os.path.join(images_dir, "*")))

                wx.MessageBox(
                    "Now that you have loaded an example pipeline, press the \"Analyze images\" button to access and"
                    " process a small image set from the CellProfiler website so you can see how CellProfiler works.",
                    "",
                    wx.ICON_INFORMATION
                )

            wx.CallAfter(load)
        except:
            wx.MessageBox(
                "CellProfiler was unable to load {}".format(pipeline_pathname),
                "Error loading pipeline",
                style=wx.OK | wx.ICON_ERROR
            )

    def __set_startup_blurb(self):
        cellprofiler.preferences.set_startup_blurb(False)
        parent = self.Parent
        while parent is not None:
            if parent.Name == "WelcomeScreenFrame":
                parent.Close()
                break
            parent = parent.Parent
