package org.apache.hawq.pxf.plugins.jdbc;
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.hawq.pxf.api.LogicalFilter;
import org.apache.hawq.pxf.plugins.jdbc.utils.DbProduct;
import org.apache.hawq.pxf.api.BasicFilter;
import org.apache.hawq.pxf.api.FilterParser;
import org.apache.hawq.pxf.api.io.DataType;
import org.apache.hawq.pxf.api.utilities.ColumnDescriptor;
import org.apache.hawq.pxf.api.utilities.InputData;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.ArrayList;
import java.util.List;
import java.text.ParseException;

/**
 * A WHERE queries builder
 *
 * Parses filter objects generated by {@link org.apache.hawq.pxf.plugins.jdbc.JdbcFilterBuilder} and builds WHERE statements
 * Only HDOP_AND is supported for multiple filters
 */
public class WhereSQLBuilder extends JdbcFilterBuilder {
    public WhereSQLBuilder(InputData input) {
        inputData = input;
    }

    /**
     * Insert WHERE constraints into a given query
     * Note that if filter is not supported, query is left unchanged
     *
     * @param dbName Database name (affects the behaviour for DATE constraints)
     * @param query SQL query to insert constraints to. The query may may contain other WHERE statements
     *
     * @throws ParseException if an error happens when parsing the constraints (provided to class constructor)
     */
    public void buildWhereSQL(String dbName, StringBuilder query) throws ParseException {
        if (!inputData.hasFilter()) {
            return;
        }

        try {
            StringBuilder prepared = new StringBuilder();
            if (!query.toString().contains("WHERE")) {
                prepared.append(" WHERE ");
            }
            else {
                prepared.append(" AND ");
            }

            // Get constraints and parse them
            String filterString = inputData.getFilterString();
            Object filterObj = getFilterObject(filterString);
            List<BasicFilter> filters = null;
            filters = convertBasicFilterList(filterObj, filters);

            String andDivisor = "";
            for (Object obj : filters) {
                prepared.append(andDivisor);
                andDivisor = " AND ";

                // Insert constraint column name
                BasicFilter filter = (BasicFilter) obj;
                ColumnDescriptor column = inputData.getColumn(filter.getColumn().index());
                prepared.append(column.columnName());

                // Insert constraint operator
                FilterParser.Operation op = filter.getOperation();
                switch (op) {
                    case HDOP_LT:
                        prepared.append(" < ");
                        break;
                    case HDOP_GT:
                        prepared.append(" > ");
                        break;
                    case HDOP_LE:
                        prepared.append(" <= ");
                        break;
                    case HDOP_GE:
                        prepared.append(" >= ");
                        break;
                    case HDOP_EQ:
                        prepared.append(" = ");
                        break;
                    case HDOP_LIKE:
                        prepared.append(" LIKE ");
                        break;
                    case HDOP_NE:
                        prepared.append(" <> ");
                        break;
                    case HDOP_IS_NULL:
                        prepared.append(" IS NULL");
                        continue;
                    case HDOP_IS_NOT_NULL:
                        prepared.append(" IS NOT NULL");
                        continue;
                    default:
                        throw new UnsupportedFilterException("Unsupported Filter operation: " + op);
                }

                // Insert constraint constant
                DbProduct dbProduct = DbProduct.getDbProduct(dbName);
                Object val = filter.getConstant().constant();
                switch (DataType.get(column.columnTypeCode())) {
                    case SMALLINT:
                    case INTEGER:
                    case BIGINT:
                    case FLOAT8:
                    case REAL:
                    case BOOLEAN:
                        prepared.append(val.toString());
                        break;
                    case TEXT:
                        prepared.append("'").append(val.toString()).append("'");
                        break;
                    case DATE:
                        // Date field has different format in different databases
                        prepared.append(dbProduct.wrapDate(val));
                        break;
                    case TIMESTAMP:
                        // Timestamp field has different format in different databases
                        prepared.append(dbProduct.wrapTimestamp(val));
                        break;
                    default:
                        throw new UnsupportedFilterException("Unsupported column type for filtering: " + column.columnTypeCode());
                }
            }

            // No exceptions were thrown, change the provided query
            query.append(prepared);
        }
        catch (UnsupportedFilterException e) {
            LOG.debug("WHERE clause is omitted: " + e.toString());
            // Silence the exception and do not insert constraints
        }
    }

    /**
     * Convert filter object into a list of {@link BasicFilter}
     *
     * @param filter Filter object
     * @param returnList A list of {@link BasicFilter} to append filters to. Must be null if the function is not called recursively
     */
    private static List<BasicFilter> convertBasicFilterList(Object filter, List<BasicFilter> returnList) throws UnsupportedFilterException {
        if (returnList == null) {
            returnList = new ArrayList<>();
        }

        if (filter instanceof BasicFilter) {
            returnList.add((BasicFilter) filter);
            return returnList;
        }

        LogicalFilter lfilter = (LogicalFilter) filter;
        if (lfilter.getOperator() != FilterParser.LogicalOperation.HDOP_AND) {
            throw new UnsupportedFilterException("Logical operation '" + lfilter.getOperator() + "' is not supported");
        }
        for (Object f : lfilter.getFilterList()) {
            returnList = convertBasicFilterList(f, returnList);
        }

        return returnList;
    }

    private static class UnsupportedFilterException extends Exception {
		UnsupportedFilterException(String message) {
            super(message);
        }
    }

    private static final Log LOG = LogFactory.getLog(WhereSQLBuilder.class);

    // {@link InputData} from PXF
    private InputData inputData;
}
