// Copyright 2019 Google LLC
//
// 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
//
//     https://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 com.google.sps;

import com.google.sps.data.ShoppingListTextEntry;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * This class generates a shopping list based on image 
 * 1) It uses cloudVisionAPI to scan an image containing shopping
 * list items and detect text from it. 
 * 2) It then uses an algorithm to create shopping sentences (queries)
 * from the text and their position. 
 * 3) This list of queries is returned to the Servlet from the method 'extractShoppingList'.
 */
public class ImageTextDectector {

  TextDetectionAPI textDetectionAPI;

  public ImageTextDectector(TextDetectionAPI textDetectionAPI) {
    this.textDetectionAPI = textDetectionAPI;
  }

  public List<String> extractShoppingList(byte[] shoppingImageBytes)
      throws IOException, PhotoDetectionException {
    List<ShoppingListTextEntry> shoppingListText = textDetectionAPI.detect(shoppingImageBytes);

    return createShoppingListQuery(shoppingListText);
  }

  /** Creates query from the text detected by cloudVision API. */
  private List<String> createShoppingListQuery(List<ShoppingListTextEntry> shoppingListText)
      throws PhotoDetectionException {
    if (shoppingListText.isEmpty()) {
      throw new PhotoDetectionException("Shopping List doesn't contain any text");
    }

    List<String> shoppingQueries = algorithm(shoppingListText);
    return shoppingQueries;
    //return PhotoShoppingUtil.formatQuery(queryItem);
  }

  private List<String> algorithm(List<ShoppingListTextEntry> shoppingListText) {
    // Create query sentences by separating out text returned by
    // cloudVisionAPI; to group shoppping items based on their position (y axis).
    int xAxisRef = 0;
    int yAxisRef = 0;
    int xAxisCurrent, yAxisCurrent;
    String sentence = "";
    List<String> shoppingQueries = new ArrayList<>();
    xAxisRef = shoppingListText.get(0).getLowerXBoundary();
    for (ShoppingListTextEntry singleWord : shoppingListText) {
        if(yAxisRef == 0) {
            yAxisRef = singleWord.getLowerYBoundary();
        }
        xAxisCurrent = singleWord.getLowerXBoundary();
        yAxisCurrent = singleWord.getLowerYBoundary();

        if(checkForSameLineWord(xAxisCurrent, yAxisCurrent, xAxisRef, yAxisRef)) {
            sentence += singleWord.getText() + " ";
        } else {
            sentence = PhotoShoppingUtil.formatQuery(sentence);
            shoppingQueries.add(sentence);
            yAxisRef = 0;
            sentence = singleWord.getText() + " ";
        }
        xAxisRef = xAxisCurrent;
    }
    sentence = PhotoShoppingUtil.formatQuery(sentence);
    shoppingQueries.add(sentence);  

    return shoppingQueries;
  }

    private boolean checkForSameLineWord(int lowerXCurrent, int lowerYCurrent, int xAxisRef, int yAxisRef) {
    /*
    ** If prevYUpper < currYLower -> Next sentence
    ** If prevXlower > currXlower -> Next sentence
    */
    int NOISE_FACTOR = 5;
    if(lowerXCurrent >= xAxisRef && 
       yAxisRef - NOISE_FACTOR <= lowerYCurrent && 
       lowerYCurrent <= yAxisRef + NOISE_FACTOR) {
        return true;
    }
    return false;
  }
}

@@ -2298,59 +2298,34 @@
 Axis
-Ref = 0;%0A    i
+Curre
 nt
+,
  yAxis
-Ref = 0;%0A    int xAxis
 Current
+Lower
 , yA
@@ -2330,24 +2330,29 @@
 yAxisCurrent
+Upper
 ;%0A    String
@@ -2425,24 +2425,34 @@
 ();%0A    
-xAxisRef
+int yAxisPrevUpper
  = shopp
@@ -2469,30 +2469,30 @@
 t.get(0).get
-LowerX
+UpperY
 Boundary();%0A
@@ -2567,48 +2567,20 @@
     
-if(yAxisRef == 0) %7B%0A            yAxisRef
+xAxisCurrent
  = s
@@ -2589,33 +2589,33 @@
 gleWord.getLower
-Y
+X
 Boundary();%0A    
@@ -2614,35 +2614,25 @@
 ();%0A        
-%7D%0A        x
+y
 AxisCurrent 
@@ -2622,32 +2622,37 @@
     yAxisCurrent
+Lower
  = singleWord.ge
@@ -2649,33 +2649,33 @@
 gleWord.getLower
-X
+Y
 Boundary();%0A    
@@ -2682,32 +2682,37 @@
     yAxisCurrent
+Upper
  = singleWord.ge
@@ -2704,35 +2704,35 @@
 = singleWord.get
-Low
+Upp
 erYBoundary();%0A%0A
@@ -2793,28 +2793,28 @@
 rent
-, xAxisRef, yAxisRef
+Lower,yAxisPrevUpper
 )) %7B
@@ -2939,32 +2939,74 @@
 uery(sentence);%0A
+            if(!sentence.isEmpty()) %7B%0A    
             shop
@@ -3048,21 +3048,9 @@
     
-yAxisRef = 0;
+%7D
 %0A   
@@ -3107,24 +3107,25 @@
       %7D%0A
+%0A
         
 xAxisRef
@@ -3120,20 +3120,26 @@
     
-x
+y
 Axis
-Ref = x
+PrevUpper = y
 Axis
@@ -3145,16 +3145,21 @@
 sCurrent
+Upper
 ;%0A    %7D%0A
@@ -3210,24 +3210,58 @@
 (sentence);%0A
+    if(!sentence.isEmpty()) %7B%0A    
     shopping
@@ -3282,18 +3282,22 @@
 ntence);
+%0A
   
+  %7D
 %0A%0A    re
@@ -3410,30 +3410,18 @@
 int 
-xAxisRef, int yAxisRef
+prevUpperY
 ) %7B%0A
@@ -3540,34 +3540,8 @@
  */%0A
-    int NOISE_FACTOR = 5;%0A
     
@@ -3544,25 +3544,25 @@
     if(lower
-X
+Y
 Current %3E= x
@@ -3562,122 +3562,19 @@
 nt %3E
-= xAxisRef && %0A       yAxisRef - NOISE_FACTOR %3C= lowerYCurrent && %0A       lowerYCurrent %3C= yAxisRef + NOISE_FACTOR
+ prevUpperY
 ) %7B%0A
@@ -3592,11 +3592,12 @@
 urn 
-tru
+fals
 e;%0A 
@@ -3608,25 +3608,24 @@
 %0A    return 
-fals
+tru
 e;%0A  %7D%0A%7D%0A

Check upper and lower y axis values