/*****************************************************************************
 *  Limpet - the Lightweight InforMation ProcEssing Toolkit
 *  http://limpet.info
 *
 *  (C) 2015-2016, Deep Blue C Technologies Ltd
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the Eclipse Public License v1.0
 *  (http://www.eclipse.org/legal/epl-v10.html)
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *****************************************************************************/
package info.limpet.analysis;

import info.limpet.IDocument;
import info.limpet.IStoreItem;
import info.limpet.impl.SampleData;
import info.limpet.operations.CollectionComplianceTests;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.measure.unit.SI;
import javax.measure.unit.Unit;

public abstract class GeneralDescription extends CoreAnalysis
{

  public GeneralDescription()
  {
    super("General Description");
  }

  private interface INumberFormatter
  {
    String format(double value);
  }

  private class MilliFormatter implements INumberFormatter
  {
    private SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");

    @Override
    public String format(double value)
    {
      return sdf.format(new Date((long) value));
    }
  }

  private class SecondFormatter implements INumberFormatter
  {
    private SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");

    @Override
    public String format(double value)
    {
      return sdf.format(new Date((long) (value / 1000d)));
    }
  }

  private class NumberFormatter implements INumberFormatter
  {
    @Override
    public String format(double value)
    {
      return "" + (int) value;
    }
  }

  private final CollectionComplianceTests aTests =
      new CollectionComplianceTests();

  @Override
  public void analyse(List<IStoreItem> selection)
  {
    List<String> titles = new ArrayList<String>();
    List<String> values = new ArrayList<String>();

    // check compatibility
    if (appliesTo(selection) && selection.size() == 1)
    {
      // ok, let's go for it.
      for (Iterator<IStoreItem> iter = selection.iterator(); iter.hasNext();)
      {
        IDocument<?> thisC = (IDocument<?>) iter.next();

        titles.add("Collection");
        values.add(thisC.getName());
        titles.add("Size");
        values.add("" + thisC.size());
        titles.add("Quantity");
        values.add("" + thisC.isQuantity());
        titles.add("Indexed");
        values.add("" + thisC.isIndexed());
        if (thisC.isIndexed())
        {
          titles.add("Index units");
          final Unit<?> indexUnits = thisC.getIndexUnits();
          if (indexUnits == null)
          {
            System.err.println(thisC + " is missing index units");
            values.add("MISSING");
          }
          else
          {
            values.add("" + thisC.getIndexUnits().toString());
          }

          final double lower = thisC.getIndexAt(0);
          final double upper = thisC.getIndexAt(thisC.size() - 1);
          final INumberFormatter formatter;
          if (indexUnits != null)
          {
            // have a go at the index range
            if (indexUnits.equals(SI.SECOND))
            {
              formatter = new SecondFormatter();
            }
            else if (indexUnits.equals(SampleData.MILLIS))
            {
              formatter = new MilliFormatter();
            }
            else
            {
              formatter = new NumberFormatter();
            }
          }
          else
          {
            formatter = new NumberFormatter();
          }

          titles.add("Index range");
          values.add(formatter.format(lower) + "-" + formatter.format(upper));
        }
      }
    }

    if (titles.size() > 0)
    {
      presentResults(titles, values);
    }

  }

  private boolean appliesTo(List<IStoreItem> selection)
  {
    return aTests.allCollections(selection);
  }

  protected abstract void presentResults(List<String> titles,
      List<String> values);
}

@@ -3150,32 +3150,109 @@
 );%0A          %7D%0A%0A
+          // check it has data%0A          if (thisC.size() %3E 0)%0A          %7B%0A  
           final 
@@ -3289,32 +3289,34 @@
 t(0);%0A          
+ 
+ 
 final double upp
@@ -3362,24 +3362,26 @@
 ;%0A          
+  
 final INumbe
@@ -3404,32 +3404,34 @@
 tter;%0A          
+ 
+ 
 if (indexUnits !
@@ -3440,32 +3440,34 @@
 null)%0A          
+  
 %7B%0A            //
@@ -3464,16 +3464,18 @@
         
+ 
+ 
 // have 
@@ -3498,16 +3498,18 @@
 x range%0A
+  
         
@@ -3546,16 +3546,18 @@
 ECOND))%0A
+  
         
@@ -3568,32 +3568,34 @@
 %7B%0A              
+  
 formatter = new 
@@ -3605,32 +3605,34 @@
 ondFormatter();%0A
+  
             %7D%0A  
@@ -3637,24 +3637,26 @@
             
+  
 else if (ind
@@ -3694,34 +3694,38 @@
 S))%0A            
-%7B%0A
+  %7B%0A  
               fo
@@ -3748,32 +3748,34 @@
 lliFormatter();%0A
+  
             %7D%0A  
@@ -3776,32 +3776,34 @@
   %7D%0A            
+  
 else%0A           
@@ -3795,34 +3795,38 @@
 lse%0A            
-%7B%0A
+  %7B%0A  
               fo
@@ -3862,32 +3862,34 @@
 ();%0A            
+  
 %7D%0A          %7D%0A  
@@ -3876,34 +3876,38 @@
     %7D%0A          
+ 
+ 
 %7D%0A
+  
           else%0A 
@@ -3907,34 +3907,38 @@
  else%0A          
-%7B%0A
+  %7B%0A  
             form
@@ -3970,35 +3970,39 @@
 er();%0A          
+ 
+ 
 %7D%0A%0A
+  
           titles
@@ -4018,24 +4018,26 @@
 ex range%22);%0A
+  
           va
@@ -4099,24 +4099,36 @@
 at(upper));%0A
+          %7D%0A
         %7D%0A  

test for zero length collection before pulling out index range