#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# Copyright (C) 2012 Glencoe Software, Inc. All Rights Reserved.
# Use is subject to license terms supplied in LICENSE.txt
#

"""
Simple command-line searching. Similar to the hql plugin.
"""


from builtins import str
import sys
import time

from Ice import OperationNotExistException
from omero.cli import CLI
from omero.plugins.hql import HqlControl
from omero.rtypes import robject


HELP = """Search for object ids by string.

Examples:

  omero search Image "my-text"
  omero search Image "with wildcard*"
  omero search Project "with wildcard*"

Examples (admin-only):

  omero search --index Image:1
  omero search --index Well:5

See also:

  https://lucene.apache.org/java/2_9_1/queryparsersyntax.html

"""


class SearchControl(HqlControl):

    def _configure(self, parser):
        parser.add_argument(
            "--index", action="store_true", default=False,
            help="Index an object as a administrator")
        parser.add_argument(
            "--no-parse",
            action="store_true",
            help="Pass the search string directly to Lucene with no parsing")
        parser.add_argument(
            "--field", nargs="*",
            default=(),
            help=("Fields which should be searched "
                  "(e.g. name, description, annotation)"))
        parser.add_argument(
            "--from",
            dest="_from",
            metavar="YYYY-MM-DD",
            type=self.date,
            help="Start date for limiting searches (YYYY-MM-DD)")
        parser.add_argument(
            "--to",
            dest="_to",
            metavar="YYYY-MM-DD",
            type=self.date,
            help="End date for limiting searches (YYYY-MM-DD)")
        parser.add_argument(
            "--date-type",
            default="import",
            choices=("acquisitionDate", "import"),
            help=("Which field to use for --from/--to "
                  "(default: acquisitionDate)"))
        parser.add_argument(
            "type",
            help="Object type to search for, e.g. 'Image' or 'Well'")
        HqlControl._configure(self, parser)
        parser.set_defaults(func=self.search)

    def date(self, user_string):
        try:
            t = time.strptime(user_string, "%Y-%m-%d")
            return time.strftime("%Y%m%d", t)
        except Exception as e:
            self.ctx.dbg(str(e))
            raise

    def search(self, args):
        c = self.ctx.conn(args)

        import omero
        import omero.all

        if args.index:
            if not self.ctx.get_event_context().isAdmin:
                self.ctx.die(432, "Only admin can index object")

            try:
                parts = args.type.split(":")
                kls = parts[0].strip()
                kls = getattr(omero.model, kls)
                kls = kls.ice_staticId()
                of = c.getCommunicator().findObjectFactory(kls)
                obj = of.create(kls)
                id = int(parts[1].strip())
                obj.setId(omero.rtypes.rlong(id))
            except Exception as e:
                self.ctx.dbg(e)
                self.ctx.die(432, "Bad object: %s" % args.type)

            c.sf.getUpdateService().indexObject(obj)

        else:
            group = None
            if args.admin:
                group = "-1"
            ctx = c.getContext(group)
            search = c.sf.createSearchService()
            try:
                try:
                    # Matching OMEROGateway.search()
                    search.setAllowLeadingWildcard(True)
                    search.setCaseSensitive(False)
                    search.onlyType(args.type)

                    if args.no_parse:
                        if args._from or args._to or args.field:
                            self.ctx.err("Ignoring from/to/fields")
                        search.byFullText(args.query)
                    else:
                        try:
                            if args.date_type == "import":
                                args.date_type = "details.creationEvent.time"
                            search.byLuceneQueryBuilder(
                                ",".join(args.field),
                                args._from, args._to, args.date_type,
                                args.query, ctx)
                        except OperationNotExistException:
                            self.ctx.err(
                                "Server does not support byLuceneQueryBuilder")
                            search.byFullText(args.query)

                    if not search.hasNext(ctx):
                        self.ctx.die(433, "No results found.")

                    self.ctx.set("search.results", [])
                    while search.hasNext(ctx):
                        results = search.results(ctx)
                        self.ctx.get("search.results").extend(results)
                        results = [[x] for x in results]
                        if not args.ids_only:
                            results = [[robject(x[0])] for x in results]
                        self.display(results,
                                     style=args.style,
                                     idsonly=args.ids_only)
                except omero.ApiUsageException as aue:
                    self.ctx.die(434, aue.message)

            finally:
                search.close()


try:
    register("search", SearchControl, HELP)
except NameError:
    if __name__ == "__main__":
        cli = CLI()
        cli.register("search", SearchControl, HELP)
        cli.invoke(sys.argv[1:])
