# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.

import mango
import unittest


class OperatorTests:
    def assertUserIds(self, user_ids, docs):
        user_ids_returned = list(d["user_id"] for d in docs)
        user_ids.sort()
        user_ids_returned.sort()
        self.assertEqual(user_ids, user_ids_returned)

    def test_all(self):
        docs = self.db.find(
            {"manager": True, "favorites": {"$all": ["Lisp", "Python"]}}
        )
        self.assertEqual(len(docs), 3)
        user_ids = [2, 12, 9]
        self.assertUserIds(user_ids, docs)

    def test_all_non_array(self):
        docs = self.db.find({"manager": True, "location": {"$all": ["Ohai"]}})
        self.assertEqual(len(docs), 0)

    def test_elem_match(self):
        emdocs = [
            {"user_id": "a", "bang": [{"foo": 1, "bar": 2}]},
            {"user_id": "b", "bang": [{"foo": 2, "bam": True}]},
        ]
        self.db.save_docs(emdocs, w=3)
        docs = self.db.find(
            {
                "_id": {"$gt": None},
                "bang": {"$elemMatch": {"foo": {"$gte": 1}, "bam": True}},
            }
        )
        self.assertEqual(len(docs), 1)
        self.assertEqual(docs[0]["user_id"], "b")

    def test_all_match(self):
        amdocs = [
            {"user_id": "a", "bang": [{"foo": 1, "bar": 2}, {"foo": 3, "bar": 4}]},
            {"user_id": "b", "bang": [{"foo": 1, "bar": 2}, {"foo": 4, "bar": 4}]},
        ]
        self.db.save_docs(amdocs, w=3)
        docs = self.db.find(
            {"bang": {"$allMatch": {"foo": {"$mod": [2, 1]}, "bar": {"$mod": [2, 0]}}}}
        )
        self.assertEqual(len(docs), 1)
        self.assertEqual(docs[0]["user_id"], "a")

    def test_empty_all_match(self):
        amdocs = [{"bad_doc": "a", "emptybang": []}]
        self.db.save_docs(amdocs, w=3)
        docs = self.db.find({"emptybang": {"$allMatch": {"foo": {"$eq": 2}}}})
        self.assertEqual(len(docs), 0)

    @unittest.skipUnless(
        not mango.has_text_service(),
        "text indexes do not support the $keyMapMatch operator",
    )
    def test_keymap_match(self):
        amdocs = [
            {"foo": {"aa": "bar", "bb": "bang"}},
            {"foo": {"cc": "bar", "bb": "bang"}},
        ]
        self.db.save_docs(amdocs, w=3)
        docs = self.db.find({"foo": {"$keyMapMatch": {"$eq": "aa"}}})
        self.assertEqual(len(docs), 1)

    def test_in_operator_array(self):
        docs = self.db.find({"manager": True, "favorites": {"$in": ["Ruby", "Python"]}})
        self.assertUserIds([2, 6, 7, 9, 11, 12], docs)

    def test_nin_operator_array(self):
        docs = self.db.find(
            {"manager": True, "favorites": {"$nin": ["Erlang", "Python"]}}
        )
        self.assertEqual(len(docs), 4)
        for doc in docs:
            if isinstance(doc["favorites"], list):
                self.assertNotIn("Erlang", doc["favorites"])
                self.assertNotIn("Python", doc["favorites"])

    def test_regex(self):
        docs = self.db.find(
            {"age": {"$gt": 40}, "location.state": {"$regex": "(?i)new.*"}}
        )
        self.assertEqual(len(docs), 2)
        self.assertUserIds([2, 10], docs)

    def test_exists_false(self):
        docs = self.db.find({"age": {"$gt": 0}, "twitter": {"$exists": False}})
        user_ids = [2, 3, 5, 6, 7, 8, 10, 11, 12, 14]
        self.assertUserIds(user_ids, docs)
        for d in docs:
            self.assertNotIn("twitter", d)

    def test_eq_null_does_not_include_missing(self):
        docs = self.db.find({"age": {"$gt": 0}, "twitter": None})
        user_ids = [9]
        self.assertUserIds(user_ids, docs)
        for d in docs:
            self.assertEqual(d["twitter"], None)

    def test_ne_includes_null_but_not_missing(self):
        docs = self.db.find({"twitter": {"$ne": "notamatch"}})
        user_ids = [0, 1, 4, 9, 13]
        self.assertUserIds(user_ids, docs)
        for d in docs:
            self.assertIn("twitter", d)

    # ideally this work be consistent across index types but, alas, it is not
    @unittest.skipUnless(
        not mango.has_text_service(),
        "text indexes do not support range queries across type boundaries",
    )
    def test_lt_includes_null_but_not_missing(self):
        docs = self.db.find({"twitter": {"$lt": 1}})
        user_ids = [9]
        self.assertUserIds(user_ids, docs)
        for d in docs:
            self.assertEqual(d["twitter"], None)

    @unittest.skipUnless(
        not mango.has_text_service(),
        "text indexes do not support range queries across type boundaries",
    )
    def test_lte_includes_null_but_not_missing(self):
        docs = self.db.find({"twitter": {"$lt": 1}})
        user_ids = [9]
        self.assertUserIds(user_ids, docs)
        for d in docs:
            self.assertEqual(d["twitter"], None)

    def test_lte_null_includes_null_but_not_missing(self):
        docs = self.db.find({"twitter": {"$lte": None}})
        user_ids = [9]
        self.assertUserIds(user_ids, docs)
        for d in docs:
            self.assertEqual(d["twitter"], None)

    def test_lte_at_z_except_null_excludes_null_and_missing(self):
        docs = self.db.find({"twitter": {"$and": [{"$lte": "@z"}, {"$ne": None}]}})
        user_ids = [0, 1, 4, 13]
        self.assertUserIds(user_ids, docs)
        for d in docs:
            self.assertNotEqual(d["twitter"], None)

    def test_range_gte_null_includes_null_but_not_missing(self):
        docs = self.db.find({"twitter": {"$gte": None}})
        self.assertGreater(len(docs), 0)
        for d in docs:
            self.assertIn("twitter", d)

    def test_exists_false_returns_missing_but_not_null(self):
        docs = self.db.find({"twitter": {"$exists": False}})
        self.assertGreater(len(docs), 0)
        for d in docs:
            self.assertNotIn("twitter", d)

    @unittest.skipUnless(
        not mango.has_text_service(),
        "text indexes do not support range queries across type boundaries",
    )
    def test_lte_respsects_unicode_collation(self):
        docs = self.db.find({"ordered": {"$lte": "a"}})
        user_ids = [7, 8, 9, 10, 11, 12]
        self.assertUserIds(user_ids, docs)

    @unittest.skipUnless(
        not mango.has_text_service(),
        "text indexes do not support range queries across type boundaries",
    )
    def test_gte_respsects_unicode_collation(self):
        docs = self.db.find({"ordered": {"$gte": "a"}})
        user_ids = [12, 13, 14]
        self.assertUserIds(user_ids, docs)


class OperatorJSONTests(mango.UserDocsTests, OperatorTests):
    pass


@unittest.skipUnless(mango.has_text_service(), "requires text service")
class OperatorTextTests(mango.UserDocsTextTests, OperatorTests):
    pass


class OperatorAllDocsTests(mango.UserDocsTestsNoIndexes, OperatorTests):
    def test_range_id_eq(self):
        doc_id = "8e1c90c0-ac18-4832-8081-40d14325bde0"
        r = self.db.find({"_id": doc_id}, explain=True, return_raw=True)

        self.assertEqual(r["mrargs"]["end_key"], doc_id)
        self.assertEqual(r["mrargs"]["start_key"], doc_id)
