package kz.cafe.admin.panels;

import java.util.*;
import kz.cafe.admin.*;
import kz.cafe.admin.constants.*;
import kz.cafe.admin.constants.AccessConstants.*;
import kz.cafe.admin.panels.model.*;
import kz.cafe.constants.*;
import kz.cafe.db.*;
import kz.cafe.db.model.*;
import kz.cafe.db.model.anotations.*;
import com.vaadin.data.*;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.ui.*;
import com.vaadin.ui.Window.*;

public class DBSingle<T> extends AbstractDBPanel<T> implements java.io.Serializable{
   private static final long serialVersionUID = -3389296171233157104L;


   private final AdminMain application;
   private final int ID;
   private final CustomDescriptor descriptor;
//   private Dimension dim;
//   private boolean isWriteable;


   private Map<String, TextField> mapTextFields = new HashMap<String, TextField>();
   private Map<String, DateField> mapDateFields = new HashMap<String, DateField>();
   private Map<String, Label>     mapImageFields = new HashMap<String, Label>();
   private Map<String, CheckBox>  mapBooleanFields = new HashMap<String, CheckBox>();



   @SuppressWarnings({ "rawtypes", "unchecked" })
   public DBSingle(AdminMain application,
                   Class<T> classDB,
                   int ID,
                   CustomDescriptor descriptor,
                   Dimension dim,
                   Set<EditMode> setMode){
      this.application = application;
      this.classDB = classDB;
      this.ID = ID;
      this.descriptor = descriptor;
//      this.dim = dim;
//      this.isWriteable = isWriteable;


      //this.setWidth("" + dim.iWidth + "px");
      //sthis.setHeight("" + dim.iHeight + "px");
      
      //this.setWidth("100%");
      //this.setHeight("100%");
      
      this.setSizeUndefined();
      


      //AbstractLayout panelLayout = (AbstractLayout) getContent();
      //panelLayout.setMargin(false);


      GridLayout layGrid = new GridLayout(2, descriptor.listFields.size() + 1);
      //layGrid.setSizeFull();


      layGrid.addComponent(new Label("Язык:"));

      CURRENT_LANG.addListener(new LLangChange());
      layGrid.addComponent(CURRENT_LANG);


      for(CustomField cf : descriptor.listFields){
         java.lang.reflect.Field field = getField(cf.db);

         if(cf.visible){

            String sClassName = field.getGenericType().toString().toLowerCase();

            if(field.isAnnotationPresent(AnnotationDate.class)){
               layGrid.addComponent(new Label(cf.name + ":  "));


               CustomDateField cdf = (CustomDateField) cf;

               DateField df = new DateField();
               df.setDateFormat(cdf.format);

               if(setMode.contains(AccessConstants.EditMode.CHANGE) && cf.isEditable){
               }
               else{
                  df.setEnabled(false);
               }

               mapDateFields.put(cf.name, df);
               layGrid.addComponent(df);
            }
            else if(field.isAnnotationPresent(AnnotationImage.class)){
               layGrid.addComponent(new Label(cf.name + ":  "));

               Label lbImage = new Label("", Label.CONTENT_XHTML);

               mapImageFields.put(cf.name, lbImage);
               layGrid.addComponent(lbImage);
            }
            else if(field.isAnnotationPresent(AnnotationIncusiveList.class) ){
               Class classDescriptor = field.getAnnotation(AnnotationIncusiveList.class).foreign();

               for(MAbstractDescriptor mAbstractDesriptor :
                           (List<MAbstractDescriptor>) MongoService.getList(classDescriptor)){

                  layGrid.addComponent(new Label(mAbstractDesriptor.name.get(InterfaceConstants.LANGS.RU) + ":  "));

                  CheckBox cb = new CheckBox();

                  if(setMode.contains(AccessConstants.EditMode.CHANGE) && cf.isEditable){
                  }
                  else{
                     cb.setEnabled(false);
                  }

                  mapBooleanFields.put(cf.name + "." + mAbstractDesriptor.ID, cb);
                  layGrid.addComponent(cb);
               }
            }
            else if(field.isAnnotationPresent(AnnotationPrice.class)){
               layGrid.addComponent(new Label(cf.name + ":  "));

               TextField tf = new TextField();

               if(setMode.contains(AccessConstants.EditMode.CHANGE) && cf.isEditable){
               }
               else{
                  tf.setEnabled(false);
               }

               mapTextFields.put(cf.name, tf);
               layGrid.addComponent(tf);
            }
            else if(sClassName.startsWith("bool")){
               layGrid.addComponent(new Label(cf.name + ":  "));

               CheckBox cb = new CheckBox();

               if(setMode.contains(AccessConstants.EditMode.CHANGE) && cf.isEditable){
               }
               else{
                  cb.setEnabled(false);
               }

               mapBooleanFields.put(cf.name, cb);
               layGrid.addComponent(cb);
            }
            else{
               layGrid.addComponent(new Label(cf.name + ":  "));

               TextField tf = new TextField();

               if(setMode.contains(AccessConstants.EditMode.CHANGE) && cf.isEditable){
               }
               else{
                  tf.setEnabled(false);
               }

               mapTextFields.put(cf.name, tf);
               layGrid.addComponent(tf);
            }
         }
      }

      this.addComponent(layGrid);

      reload();
   }




   @SuppressWarnings({ "unchecked", "rawtypes" })
   public void reload(){
      for(CustomField cf : descriptor.listFields){
         if(cf.visible){
            java.lang.reflect.Field field = getField(cf.db);

            Object objFieldValue;
            try{
               objFieldValue = getFieldValue(field, MongoService.get(classDB, ID));
            }
            catch (Throwable e1){
               application.getMainWindow().showNotification(
                                 "Этот объект удален из базы",
                                 Notification.TYPE_ERROR_MESSAGE
                                );
               return;
            }


            String sClassName = field.getGenericType().toString().toLowerCase();

            //Date
            if(field.isAnnotationPresent(AnnotationDate.class) ){

               mapDateFields.get(cf.name).setValue(new Date((Long) objFieldValue));
            }
            //Price
            else if(field.isAnnotationPresent(AnnotationPrice.class)){
               mapTextFields.get(cf.name).setValue(formatPrice(objFieldValue));
            }
            //Combo
            else if(cf instanceof CustomFixedComboField){
               CustomFixedComboField cdf = (CustomFixedComboField) cf;

               if(field.isAnnotationPresent(AnnotationRelated.class) ){
                  Class classForeign =
                           field.getAnnotation(AnnotationRelated.class).foreign();

                  localizeCombos(cdf, classForeign);
               }

               try{
                  Integer id = (Integer) objFieldValue;
                  mapTextFields.get(cf.name).setValue((cdf.get(id)).text);
               }
               catch (Throwable e){
               }
            }
            
            
            //Password
            else if(cf instanceof CustomPassword){
               if(application.isAdmin){
                  try{
                     mapTextFields.get(cf.name).setValue(("" + objFieldValue));
                  }
                  catch (Throwable e){
                  }
               }
               else{
                  mapTextFields.get(cf.name).setValue("*****");
               }
            }

            //Image
            else if(field.isAnnotationPresent(AnnotationImage.class) ){
               mapImageFields.get(cf.name).setValue(image2ClickableText("" + objFieldValue, 150));
            }


            //Multilang
            else if(field.isAnnotationPresent(AnnotationMultiLangString.class) ){
               Map<InterfaceConstants.LANGS, String> map =
                                            (Map<InterfaceConstants.LANGS, String>) objFieldValue;

               String sValue =
                        map.get(InterfaceConstants.LANGS.valueOf("" + CURRENT_LANG.getValue()));

               if(sValue == null){
                  sValue = "";
               }


               mapTextFields.get(cf.name).setValue(sValue);
            }

            else if(field.isAnnotationPresent(AnnotationIncusiveList.class) ){
               Class classDescriptor = field.getAnnotation(AnnotationIncusiveList.class).foreign();
               
               Set<Integer> set = (Set<Integer>) objFieldValue;

               for(MAbstractDescriptor mAbstractDesriptor :
                           (List<MAbstractDescriptor>) MongoService.getList(classDescriptor)){
                  
                  if(set.contains(mAbstractDesriptor.ID)){
                     mapBooleanFields.get(cf.name + "." + mAbstractDesriptor.ID).setValue(true);
                  }
                  else{
                     mapBooleanFields.get(cf.name + "." + mAbstractDesriptor.ID).setValue(false);
                  }
               }
            }
//            else if(field.isAnnotationPresent(AnnotationPrice.class) ){
//               table.addContainerProperty(cstField.name, String.class, null);
//            }
//            else if(sClassName.contains("integer")){
//               table.addContainerProperty(cstField.name, Integer.class, null);
//            }
//            else if(sClassName.contains("long")){
//               table.addContainerProperty(cstField.name, Long.class, null);
//            }

            else if(sClassName.startsWith("bool")){
               mapBooleanFields.get(cf.name).setValue(objFieldValue);
            }

//            else if(sClassName.contains("float")){
//               table.addContainerProperty(cstField.name, Float.class, null);
//            }
//            else if(sClassName.contains("double")){
//               table.addContainerProperty(cstField.name, Double.class, null);
//            }
            else{
               try{
                  mapTextFields.get(cf.name).setValue("" + objFieldValue);
               }
               catch (Throwable e){
               }
            }
         }
      }
   }





   private class LLangChange implements Property.ValueChangeListener{
      private static final long serialVersionUID = 8110274065919013532L;

      @Override
      public void valueChange(ValueChangeEvent event){
         application.lang = (InterfaceConstants.LANGS) CURRENT_LANG.getValue();

         reload();
      }
   }

}
