package it.unibz.inf.ontop.owlrefplatform.core.queryevaluation;


/*
 * #%L
 * ontop-reformulation-core
 * %%
 * Copyright (C) 2009 - 2014 Free University of Bozen-Bolzano
 * %%
 * 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.
 * #L%
 */

import java.util.regex.Pattern;

public class H2SQLDialectAdapter extends SQL99DialectAdapter {

	@Override
	public String strUuid(){
		return "RANDOM_UUID()";
	}

	@Override
	public String uuid(){
		return strConcat(new String[]{"'urn:uuid:'","RANDOM_UUID()"});
	}

	@Override
	public String SHA256(String str){
		return String.format("HASH('SHA256', STRINGTOUTF8(%s),1)", str);
	}


	@Override
	public String sqlSlice(long limit, long offset) {
		if (limit < 0 ) {
			if (offset < 0) {

				// If both limit and offset is not specified.
				return "";

			} else {
				// Max limit: http://www.h2database.com/html/advanced.html#limits_limitations
				return String.format("LIMIT %d,2147483647", offset);
			}
		} else {
			if (offset < 0) {
				// If the offset is not specified
				return String.format("LIMIT %d", limit);
			} else {
				return String.format("LIMIT %d,%d", offset, limit);
			}
		}
	}
	
	@Override
	public String sqlRegex(String columnname, String pattern, boolean caseinSensitive, boolean multiLine, boolean dotAllMode) {
        Pattern quotes = Pattern.compile("[\"`\\['].*[\"`\\]']");
        if(quotes.matcher(pattern).matches() ) {
            pattern = pattern.substring(1, pattern.length() - 1); // remove the
            // enclosing
            // quotes
        }
		// embedded options: 
		
		String pflags = "(?";
		if (multiLine)
			pflags += "m"; // equivalent of Pattern.MULTILINE
		if (dotAllMode)
			pflags += "s"; // equivalent of Pattern.DOTALL
		pflags +=")";
		return columnname + " ~" + ((caseinSensitive) ? "* " : " ") + "'"+ ((multiLine || dotAllMode) ? pflags : "") + pattern + "'";
	}

    @Override
    public String strReplace(String str, String oldstr, String newstr) {
        oldstr = oldstr.substring(1, oldstr.length() - 1); // remove the enclosing quotes

        newstr = newstr.substring(1, newstr.length() - 1);
        return String.format("REGEXP_REPLACE(%s, '%s', '%s')", str, oldstr, newstr);
    }

	@Override
	public String getDummyTable() {
		return "SELECT 1";
	}
	
	@Override 
	public String getSQLLexicalFormBoolean(boolean value) {
		return value ? 	"TRUE" : "FALSE";
	}

	/***
	 * Given an XSD dateTime this method will generate a SQL TIMESTAMP value.
	 * The method will strip any fractional seconds found in the date time
	 * (since we haven't found a nice way to support them in all databases). It
	 * will also normalize the use of Z to the timezome +00:00 and last, if the
	 * database is H2, it will remove all timezone information, since this is
	 * not supported there.
	 * 
	 * @param
	 * @return
	 */
	@Override
	public String getSQLLexicalFormDatetime(String v) {
		String datetime = v.replace('T', ' ');
		int dotlocation = datetime.indexOf('.');
		int zlocation = datetime.indexOf('Z');
		int minuslocation = datetime.indexOf('-', 10); // added search from 10th pos, because we need to ignore minuses in date
		int pluslocation = datetime.indexOf('+');
		StringBuilder bf = new StringBuilder(datetime);
		if (zlocation != -1) {
			/*
			 * replacing Z by +00:00
			 */
			bf.replace(zlocation, bf.length(), "+00:00");
		}

		if (dotlocation != -1) {
			/*
			 * Stripping the string from the presicion that is not supported by
			 * SQL timestamps.
			 */
			// TODO we need to check which databases support fractional
			// sections (e.g., oracle,db2, postgres)
			// so that when supported, we use it.
			int endlocation = Math.max(zlocation, Math.max(minuslocation, pluslocation));
			if (endlocation == -1) {
				endlocation = datetime.length();
			}
			bf.replace(dotlocation, endlocation, "");
		}
		if (bf.length() > 19) {
			bf.delete(19, bf.length());
		}
		bf.insert(0, "'");
		bf.append("'");
		
		return bf.toString();
	}
	
}

@@ -1125,17 +1125,16 @@
 r);%0A%09%7D%0A%0A
-%0A
 %09@Overri
@@ -1195,95 +1195,89 @@
 %09%09if
- 
 (limit 
-%3C 0 ) %7B%0A%09%09%09if (offset %3C 0) %7B%0A%0A%09%09%09%09// If both limit and offset is not specified.
+== 0)%7B%0A%09%09%09return %22LIMIT 0%22;%0A%09%09%7D%0A%0A%09%09if (limit %3C 0)  %7B%0A%09%09%09if (offset %3C 0 ) %7B
 %0A%09%09%09
@@ -1288,17 +1288,16 @@
 urn %22%22;%0A
-%0A
 %09%09%09%7D els
@@ -1304,89 +1304,8 @@
 e %7B%0A
-%09%09%09%09// Max limit: http://www.h2database.com/html/advanced.html#limits_limitations
 %0A%09%09%09
@@ -1331,27 +1331,22 @@
 at(%22
-LIMIT %25d,2147483647
+OFFSET %25d ROWS
 %22, o
@@ -1454,24 +1454,54 @@
 format(%22
-LIMIT %25d
+OFFSET 0 ROWS%5CnFETCH NEXT %25d ROWS ONLY
 %22, limit
@@ -1545,19 +1545,47 @@
 at(%22
-LIMIT %25d,%25d
+OFFSET %25d ROWS%5CnFETCH NEXT %25d ROWS ONLY
 %22, o

Fix H2 OFFSET.