# Copyright 2019 Google LLC
#
# 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
#
#     https://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.

from django.db.models.lookups import (
    EndsWith, IEndsWith, IStartsWith, StartsWith,
)


def endswith(self, compiler, connection):
    lhs_sql, params = self.process_lhs(compiler, connection)
    rhs_sql, rhs_params = self.process_rhs(compiler, connection)
    params.extend(rhs_params)
    rhs_sql = self.get_rhs_op(connection, rhs_sql)
    # Chop leading '%' from param since this isn't a LIKE query.
    params[0] = params[0][1:]
    # rhs_sql is 'STARTS_WITH(%s, %%s)' and lhs_sql is the column name.
    return rhs_sql % lhs_sql, params


def startswith(self, compiler, connection):
    # Same logic as endswith but chop trailing (rather than leading) '%' from
    # param.
    lhs_sql, params = self.process_lhs(compiler, connection)
    rhs_sql, rhs_params = self.process_rhs(compiler, connection)
    params.extend(rhs_params)
    rhs_sql = self.get_rhs_op(connection, rhs_sql)
    params[0] = params[0][:-1]
    return rhs_sql % lhs_sql, params


def istartswith(self, compiler, connection):
    lhs_sql, params = self.process_lhs(compiler, connection)
    rhs_sql, rhs_params = self.process_rhs(compiler, connection)
    params.extend(rhs_params)
    rhs_sql = self.get_rhs_op(connection, rhs_sql)
    params[0] = "^(?i)%s" % params[0][:-1]
    return rhs_sql % lhs_sql, params


def iendswith(self, compiler, connection):
    lhs_sql, params = self.process_lhs(compiler, connection)
    rhs_sql, rhs_params = self.process_rhs(compiler, connection)
    params.extend(rhs_params)
    rhs_sql = self.get_rhs_op(connection, rhs_sql)
    params[0] = "(?i)%s$" % params[0][1:]
    return rhs_sql % lhs_sql, params


def register_lookups():
    EndsWith.as_spanner = endswith
    IEndsWith.as_spanner = iendswith
    StartsWith.as_spanner = startswith
    IStartsWith.as_spanner = istartswith

@@ -666,16 +666,27 @@
 )%0A%0A%0Adef 
+startswith_
 endswith
@@ -707,32 +707,100 @@
 r, connection):%0A
+    %22%22%22startswith, endswith, istartswith, and iendswith lookups.%22%22%22%0A
     lhs_sql, par
@@ -1005,16 +1005,20 @@
 hop 
+the 
 leading 
 '%25' 
@@ -1017,859 +1017,439 @@
 ing 
-'%25' from param since this isn't a LIKE query.%0A    params%5B0%5D = params%5B0%5D%5B1:%5D%0A    # rhs_sql is 'STARTS_WITH(%25s, %25%25s)' and lhs_sql is the column name.%0A    return rhs_sql %25 lhs_sql, params%0A%0A%0Adef startswith(self, compiler, connection):%0A    # Same logic as endswith but chop trailing (rather than leading) '%25' from%0A    # param.%0A    lhs_sql, params = self.process_lhs(compiler, connection)%0A    rhs_sql, rhs_params = self.process_rhs(compiler, connection)%0A    params.extend(rhs_params)%0A    rhs_sql = self.get_rhs_op(connection, rhs_sql)%0A    params%5B0%5D = params%5B0%5D%5B:-1%5D%0A    return rhs_sql %25 lhs_sql, params%0A%0A%0Adef istartswith(self, compiler, connection):%0A    lhs_sql, params = self.process_lhs(compiler, connection)%0A    rhs_sql, rhs_params = self.process_rhs(compiler, connection)%0A    params.extend(rhs_params)%0A    rhs_sql = self.get_rhs_op(connection, rhs_sql)%0A
+(endswith) or trailing (startswith) percent sign that%0A    # Django adds to the param since this isn't a LIKE query as Django expects.%0A    if 'endswith' in self.lookup_name:%0A        params%5B0%5D = params%5B0%5D%5B1:%5D%0A    else:%0A        params%5B0%5D = params%5B0%5D%5B:-1%5D%0A    # Construct the regex for istartswith or iendswith.%0A    if self.lookup_name.startswith('i'):%0A        regex = '%5E(?i)%25s' if self.lookup_name == 'istartswith' else '(?i)%25s$'%0A    
     
@@ -1464,17 +1464,13 @@
 %5D = 
-%22%5E(?i)%25s%22
+regex
  %25 p
@@ -1481,344 +1481,120 @@
 s%5B0%5D
-%5B:-1%5D%0A    return rhs_sql %25 lhs_sql, params%0A%0A%0Adef iendswith(self, compiler, connection):%0A    lhs_sql, params = self.process_lhs(compiler, connection)%0A    rhs_sql, rhs_params = self.process_rhs(compiler, connection)%0A    params.extend(rhs_params)
+%0A    # rhs_sql is e.g. 'STARTS_WITH(%25s, %25%25s)' or REGEXP_CONTAINS(%25s, %25%25s), and
 %0A    
-r
+# l
 hs_sql 
-= self.get_rhs_op(connection, rhs_sql)%0A    params%5B0%5D = %22(?i)%25s$%22 %25 params%5B0%5D%5B1:%5D
+is the column name.
 %0A   
@@ -1679,16 +1679,27 @@
 anner = 
+startswith_
 endswith
@@ -1726,17 +1726,27 @@
 anner = 
-i
+startswith_
 endswith
@@ -1780,24 +1780,33 @@
 = startswith
+_endswith
 %0A    IStarts
@@ -1823,17 +1823,16 @@
 anner = 
-i
 startswi
@@ -1829,13 +1829,22 @@
 = startswith
+_endswith
 %0A

unify startswith, endswith, istartswith, and iendswith lookups