package com.raizlabs.android.dbflow.sql.language;

import com.raizlabs.android.dbflow.sql.Query;
import com.raizlabs.android.dbflow.sql.QueryBuilder;
import com.raizlabs.android.dbflow.sql.language.property.IProperty;
import com.raizlabs.android.dbflow.sql.language.property.Property;

import java.util.ArrayList;
import java.util.List;

/**
 * Description: Represents a SQLITE CASE argument.
 */
public class Case<TReturn> implements Query {

    private IProperty caseColumn;
    private List<CaseCondition<TReturn>> caseConditions = new ArrayList<>();
    private String columnName;
    private TReturn elseValue;
    private boolean elseSpecified = false;

    // when true, only WHEN value is supported. Not WHEN condition
    private boolean efficientCase = false;

    Case() {
    }

    Case(IProperty caseColumn) {
        this.caseColumn = caseColumn;
        efficientCase = true;
    }

    public CaseCondition<TReturn> when(SQLCondition sqlCondition) {
        if (efficientCase) {
            throw new IllegalStateException("When using the efficient CASE method," +
                    "you must pass in value only, not condition.");
        }
        CaseCondition<TReturn> caseCondition = new CaseCondition<>(this, sqlCondition);
        caseConditions.add(caseCondition);
        return caseCondition;
    }

    public CaseCondition<TReturn> when(TReturn whenValue) {
        if (!efficientCase) {
            throw new IllegalStateException("When not using the efficient CASE method, " +
                    "you must pass in the SQLConditions as a parameter");
        }
        CaseCondition<TReturn> caseCondition = new CaseCondition<>(this, whenValue);
        caseConditions.add(caseCondition);
        return caseCondition;
    }

    public CaseCondition<TReturn> when(IProperty property) {
        if (!efficientCase) {
            throw new IllegalStateException("When not using the efficient CASE method, " +
                    "you must pass in the SQLCondition as a parameter");
        }
        CaseCondition<TReturn> caseCondition = new CaseCondition<>(this, property);
        caseConditions.add(caseCondition);
        return caseCondition;
    }

    /**
     * Default case here. If not specified, value will be NULL.
     */
    public Case<TReturn> _else(TReturn elseValue) {
        this.elseValue = elseValue;
        elseSpecified = true; // ensure its set especially if null specified.
        return this;
    }

    /**
     * @param columnName The name of the case that we return in a column.
     * @return The final name given to this case.
     */
    public Property<Case<TReturn>> end(String columnName) {
        this.columnName = QueryBuilder.quoteIfNeeded(columnName);
        return new Property<>(null, NameAlias.rawBuilder(getQuery())
                .build());
    }

    boolean isEfficientCase() {
        return efficientCase;
    }

    @Override
    public String getQuery() {
        QueryBuilder queryBuilder = new QueryBuilder(" CASE");
        if (isEfficientCase()) {
            queryBuilder.append(" " + BaseCondition.convertValueToString(caseColumn, false));
        }
        //noinspection unchecked
        queryBuilder.appendList(caseConditions);
        if (elseSpecified) {
            queryBuilder.append(" ELSE ").append(BaseCondition.convertValueToString(elseValue, false));
        }
        if (columnName != null) {
            queryBuilder.append(" END " + columnName);
        }
        return queryBuilder.getQuery();
    }
}

@@ -44,16 +44,61 @@
 guage;%0A%0A
+import android.support.annotation.Nullable;%0A%0A
 import c
@@ -806,24 +806,67 @@
 e = false;%0A%0A
+    private boolean endSpecified = false;%0A%0A
     Case() %7B
@@ -2648,37 +2648,36 @@
 The 
-final name given to this case
+case completed as a property
 .%0A  
@@ -2721,16 +2721,26 @@
 n%3E%3E end(
+@Nullable 
 String c
@@ -2748,24 +2748,91 @@
 lumnName) %7B%0A
+        endSpecified = true;%0A        if (columnName != null) %7B%0A    
         this
@@ -2877,32 +2877,42 @@
 ed(columnName);%0A
+        %7D%0A
         return n
@@ -2994,24 +2994,165 @@
 ());%0A    %7D%0A%0A
+    /**%0A     * @return The case completed as a property.%0A     */%0A    public Property%3CCase%3CTReturn%3E%3E end() %7B%0A        return end(null);%0A    %7D%0A%0A
     boolean 
@@ -3690,34 +3690,28 @@
     if (
-columnName != null
+endSpecified
 ) %7B%0A    
@@ -3748,16 +3748,17 @@
 END %22 + 
+(
 columnNa
@@ -3751,32 +3751,59 @@
  %22 + (columnName
+ != null ? columnName : %22%22)
 );%0A        %7D%0A   

add support for empty column name at end of case.