package com.atlassian.bitbucket.ao;

import com.atlassian.activeobjects.external.ActiveObjects;
import com.atlassian.activeobjects.spi.DatabaseType;
import com.atlassian.bitbucket.util.PageRequest;
import com.google.common.base.Joiner;
import net.java.ao.Query;

import javax.annotation.Nonnull;

import static java.util.Objects.requireNonNull;

public class AoUtils {

    private AoUtils() {
        throw new UnsupportedOperationException(getClass().getSimpleName() + " cannot be initialised");
    }

    /**
     * Get name of string length function for database used by Active Objects.
     * @param ao Active Objects instance
     * @return name of string length function, e.g. LEN (MS SQL Server) or LENGTH (other supported DB)
     */
    public static String lengthFunction(@Nonnull ActiveObjects ao) {
        if (requireNonNull(ao, "ao").moduleMetaData().getDatabaseType() == DatabaseType.MS_SQL) {
            return "LEN";
        }
        return "LENGTH";
    }

    /**
     * Create a query selecting the given fields.
     * @param fields the fields to select
     * @return a new query
     */
    public static Query newQuery(String... fields) {
        return fields.length > 0 ?
                Query.select(Joiner.on(',').join(fields)) :
                Query.select();
    }

    /**
     * Quote provided value if needed. Current implementation quotes value if PostgreSQL is used for Active Objects.
     * Useful for table and column names.
     * @param ao Active Objects instance
     * @param value value to be quoted
     * @return value, quoted if needed
     */
    public static String quote(@Nonnull ActiveObjects ao, @Nonnull String value) {
        if (requireNonNull(ao, "ao").moduleMetaData().getDatabaseType() == DatabaseType.POSTGRESQL) {
            return "\"" + requireNonNull(value, "value") + "\"";
        }
        return value;
    }

    /**
     * Restrict a query to a given offset and limit
     * @param query the query to restrict
     * @param pageRequest the pageRequest to use for restricting
     * @return the query
     */
    public static Query restrict(Query query, PageRequest pageRequest) {
        return query.offset(pageRequest.getStart())
                // +1 so that we know if it is the last page
                .limit(pageRequest.getLimit() + 1);
    }

}
