/*
 * Copyright 2011 JBoss Inc
 *
 * 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.
 */

package org.drools.guvnor.client.decisiontable.analysis;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.drools.ide.common.client.modeldriven.SuggestionCompletionEngine;
import org.drools.ide.common.client.modeldriven.dt52.Analysis;
import org.drools.ide.common.client.modeldriven.dt52.ConditionCol52;
import org.drools.ide.common.client.modeldriven.dt52.DTCellValue52;
import org.drools.ide.common.client.modeldriven.dt52.GuidedDecisionTable52;
import org.drools.ide.common.client.modeldriven.dt52.LimitedEntryCol;
import org.drools.ide.common.client.modeldriven.dt52.Pattern52;

public class DecisionTableAnalyzer {

    private SuggestionCompletionEngine sce;

    public DecisionTableAnalyzer(SuggestionCompletionEngine sce) {
        this.sce = sce;
    }

    public List<Analysis> analyze(GuidedDecisionTable52 modelWithWrongData, List<List<DTCellValue52>> data) {
        return detectImpossibleMatches(modelWithWrongData, data);
    }

    private List<Analysis> detectImpossibleMatches(GuidedDecisionTable52 modelWithWrongData, List<List<DTCellValue52>> data) {
        List<Analysis> analysisData = new ArrayList<Analysis>(data.size());
        for (List<DTCellValue52> row : data) {
            long rowIndex = row.get(0).getNumericValue().longValue();
            Analysis analysis = new Analysis();
            analysisData.add(analysis);
            for (Pattern52 pattern : modelWithWrongData.getConditionPatterns()) {
                List<ConditionCol52> conditions = pattern.getConditions();
                Map<String, FieldDetector> detectorMap = new HashMap<String, FieldDetector>(
                        conditions.size());
                for (ConditionCol52 conditionCol : conditions) {
                    int columnIndex = modelWithWrongData.getAllColumns().indexOf(conditionCol);
                    DTCellValue52 value = row.get(columnIndex);
                    if (value.hasValue()) {
                        FieldDetector newDetector = buildDetector(modelWithWrongData, conditionCol, value);
                        if (newDetector != null) {
                            String factField = conditionCol.getFactField();
                            FieldDetector detector = detectorMap.get(factField);
                            if (detector == null) {
                                detector = newDetector;
                                detectorMap.put(factField, detector);
                            } else {
                                boolean previousImpossibleMatch = detector.isImpossibleMatch();
                                detector.merge(newDetector);
                                if (!previousImpossibleMatch && detector.isImpossibleMatch()) {
                                    analysis.addImpossibleMatch("Impossible match on " + factField);
                                }
                            }
                        }
                    }
                }
            }
        }
        return analysisData;
    }

    private FieldDetector buildDetector(GuidedDecisionTable52 model, ConditionCol52 conditionCol,
            DTCellValue52 value) {
        FieldDetector newDetector;
        String operator = conditionCol.getOperator();
        if (conditionCol instanceof LimitedEntryCol) {
            newDetector = new BooleanFieldDetector(value.getBooleanValue(), operator);
        } else {
            //Extended Entry...
            String type = model.getType( conditionCol, sce );
            //Retrieve "Guvnor" enums
            String[] allValueList = model.getValueList( conditionCol, sce );
            if (allValueList.length != 0) {
                // use vals
                newDetector = new EnumFieldDetector(Arrays.asList(allValueList), value.getStringValue(), operator);
            } else if ( type == null ) {
                // Null means the field is free-format
                newDetector = null;
            } else if ( type.equals( SuggestionCompletionEngine.TYPE_STRING ) ) {
                newDetector = new StringFieldDetector(value.getStringValue(), operator);
            } else if ( type.equals( SuggestionCompletionEngine.TYPE_NUMERIC ) ) {
                newDetector = new NumericFieldDetector(value.getNumericValue(), operator);
            } else if ( type.equals( SuggestionCompletionEngine.TYPE_BOOLEAN ) ) {
                newDetector = new BooleanFieldDetector(value.getBooleanValue(), operator);
            } else if ( type.equals( SuggestionCompletionEngine.TYPE_DATE ) ) {
                newDetector = new DateFieldDetector(value.getDateValue(), operator);
            } else {
                newDetector = null;
            }
        }
        return newDetector;
    }

}

@@ -2230,17 +2230,22 @@
 tector%3E 
-d
+fieldD
 etectorM
@@ -2631,32 +2631,37 @@
 ieldDetector new
+Field
 Detector = build
@@ -2738,24 +2738,29 @@
      if (new
+Field
 Detector != 
@@ -2885,17 +2885,22 @@
 etector 
-d
+fieldD
 etector 
@@ -2901,17 +2901,22 @@
 ector = 
-d
+fieldD
 etectorM
@@ -2966,17 +2966,22 @@
     if (
-d
+fieldD
 etector 
@@ -3019,25 +3019,30 @@
             
-d
+fieldD
 etector = ne
@@ -3038,24 +3038,29 @@
 tector = new
+Field
 Detector;%0A  
@@ -3085,25 +3085,30 @@
             
-d
+fieldD
 etectorMap.p
@@ -3121,17 +3121,22 @@
 tField, 
-d
+fieldD
 etector)
@@ -3240,17 +3240,22 @@
 Match = 
-d
+fieldD
 etector.
@@ -3307,17 +3307,22 @@
         
-d
+fieldD
 etector.
@@ -3330,16 +3330,21 @@
 erge(new
+Field
 Detector
@@ -3410,17 +3410,22 @@
 atch && 
-d
+fieldD
 etector.

rename DisjointDetector to FieldDetector => variables