<commit_before>package de.fau.cs.mad.gamekobold.template_generator;



import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;

import de.fau.cs.mad.gamekobold.R;
import de.fau.cs.mad.gamekobold.SlideoutNavigationActivity;
import de.fau.cs.mad.gamekobold.character.CharacterEditActivity;
import de.fau.cs.mad.gamekobold.character.CustomExpandableListAdapter;
import de.fau.cs.mad.gamekobold.jackson.CheckBoxClass;
import de.fau.cs.mad.gamekobold.jackson.ColumnHeader;
import de.fau.cs.mad.gamekobold.jackson.IEditableContent;
import de.fau.cs.mad.gamekobold.jackson.PopupClass;
import de.fau.cs.mad.gamekobold.jackson.StringClass;
import de.fau.cs.mad.gamekobold.jackson.Table;
import de.fau.cs.mad.gamekobold.matrix.MatrixFragment;
import de.fau.cs.mad.gamekobold.matrix.MatrixItem;
import de.fau.cs.mad.gamekobold.template_generator.SessionMonitorEditText.OnEditSessionCompleteListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
import android.support.v4.app.Fragment;
import android.support.v4.app.DialogFragment;
import android.support.v4.widget.SearchViewCompat;
import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TableRow.LayoutParams;
import android.widget.TextView;
import android.widget.ToggleButton;

@SuppressLint("NewApi")
public class TableFragment extends GeneralFragment implements OnCheckedChangeListener{
	/*
	 * JACKSON START
	 */
	Table jacksonTable;
	boolean jacksonInflateWithData = false;
	/*
	 * JACKSON END
	 */
	
	enum content_type{
		editText, checkbox, popup;
	}
	
	View mainView;
	TableLayout table;
	TableLayout headerTable;
	// also set in createTableHeader !! onCreate is called when orientation is rotated ->
	// amountColumns = #before change but we recreate the header table with 2 columns
	int amountColumns = 2;
//	AlertDialog dialog;
//	TableLayout dialogTable;
	SessionMonitorEditText dialogRowCounter = null;
	//menu shown when long clicking a row
	protected TableRow contextMenuRow;
//	protected ArrayList<View> popupViewList = new ArrayList<>();
//	protected ArrayList<PopupWindow> popupList = new ArrayList<>();


	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);   
        setRetainInstance(true);
    	LayoutInflater inflater = (LayoutInflater) SlideoutNavigationActivity.theActiveActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if(SlideoutNavigationActivity.theActiveActivity instanceof TemplateGeneratorActivity){
//			Log.d("TableFragment", "inflated for TemplateGenerator");
        	//create the table that will be shown in the dialog
        	mainView = (RelativeLayout) inflater.inflate(R.layout.template_generator_table_view, new LinearLayout(getActivity()), false);
        	table = (TableLayout) mainView.findViewById(R.id.template_generator_table);
        	createTableHeader();
        	//set the 3 buttons
        	Button buttonAdd = (Button)mainView.findViewById(R.id.add_row);
        	buttonAdd.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
        			addItemList();
        		}
        	});
        	Button addColumnButton = (Button)mainView.findViewById(R.id.add_column);
        	addColumnButton.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
        			addColumn();
        		}
        	});
        	Button removeColumnButton = (Button)mainView.findViewById(R.id.remove_column);
        	removeColumnButton.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
        			removeColumn();
        		}
        	});
        	TextView addRowBelow = (TextView)mainView.findViewById(R.id.add_below);
        	addRowBelow.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
        			addItemList();
        		}
        	});
        	setAddButtonStyle(addRowBelow);
        }
        else if(SlideoutNavigationActivity.theActiveActivity instanceof CharacterEditActivity){
			Log.d("TableFragment", "inflated for CharacterEditActivity");
        	mainView = (RelativeLayout) inflater.inflate(R.layout.character_edit_table_view, new LinearLayout(getActivity()), false);
        }
		// removed because we could otherwise not save/load tables with 0 rows
		//addItemList();
    }
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		super.onCreateView(inflater, container, savedInstanceState);
		// JACKSON START
		if(SlideoutNavigationActivity.theActiveActivity instanceof TemplateGeneratorActivity){
			// check for saved rows
			table.removeAllViews();
			if(jacksonTable.getRowCount() > 0) {
				jacksonInflateWithData = true;
				// adjust row count
				final int jacksonRowNum = jacksonTable.getRowCount();
				while(table.getChildCount() < jacksonRowNum) {
					// TODO hier die rows laden
//					addItemList();
					final int columnCount = jacksonTable.getNumberOfColumns();
			        final TableRow row = new TableRow(getActivity());
			        registerForContextMenu(row);
					for(int i = 0 ; i < columnCount; i++) {
						final int rowIndex = table.getChildCount();
						final ColumnHeader header = jacksonTable.getColumnHeader(i);
						View newElement;
						if(header.isString()) {
							newElement = initEditText(row, jacksonTable.getEntry(i, rowIndex));
						}
						else if(header.isCheckBox()) {
							newElement = initCheckBox(row, jacksonTable.getEntry(i, rowIndex));
						}
						else {
							newElement = initPopup(row, jacksonTable.getEntry(i, rowIndex));
						}
						row.addView(newElement);
					}
			        table.addView(row);
					Log.d("TableFragment", "added row");
				}
				while(table.getChildCount() > jacksonRowNum) {
					removeRow((TableRow)table.getChildAt(table.getChildCount()-1));
					Log.d("TableFragment", "removed row");
				}
				jacksonInflateWithData = false;
			}
			else {
				addItemList();
			}
		}
		else if(SlideoutNavigationActivity.theActiveActivity instanceof CharacterEditActivity){
			// check for saved rows
			fillListView();
		}
		//
		// JACKSON END
		//
		return mainView;
	}
	
	
	private void fillListView(){
		final int jacksonTableColumnNumber = jacksonTable.getNumberOfColumns();
		final int jacksonRowNum = jacksonTable.getRowCount();

		// check if we got any saved columns (they are only created if user goes into table!)
		// so if there are no saved columns or we didn't load any data we add the default columns 
		
//		jacksonTable.getEntry(columnIndex, rowIndex)
//		List<String> your_array_list = new ArrayList<String>();
//        your_array_list.add("foo");
//		ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
//                this, 
//                android.R.layout.simple_list_item_1,
//                your_array_list );
		String[] groupList = new String[jacksonRowNum];
		String[][] itemList = new String[jacksonRowNum][];
		for(int rowIndex=0; rowIndex<jacksonRowNum; rowIndex++){
			groupList[rowIndex] = jacksonTable.getEntry(0, rowIndex).getContent();
		}
		
		for(int rowIndex=0; rowIndex<jacksonRowNum; rowIndex++){
			itemList[rowIndex] = new String[jacksonTableColumnNumber-1];
			for(int columnIndex=1; columnIndex<jacksonTableColumnNumber; columnIndex++){
//				View firstRowView = null;
				//TODO: get saved table type from jackson here
				//now just assume it is edittext
//				TableRow firstRow = (TableRow) table.getChildAt(0);
				IEditableContent jacksonEntry = null;
				jacksonEntry = jacksonTable.getEntry(columnIndex, rowIndex);
//				if(firstRow != null){
//					firstRowView = firstRow.getChildAt(columnIndex);
//				}
//				if(firstRowView instanceof EditText){
//					jacksonEntry = jacksonTable.getEntry(columnIndex, rowIndex);
//				}
//				else if(firstRowView instanceof LinearLayout){
//					if(((LinearLayout) firstRowView).getChildAt(0) instanceof CheckBox){
//						jacksonEntry = jacksonTable.getEntry(columnIndex, rowIndex);
//					}
//					else{// if(((LinearLayout) firstRowView).getChildAt(0) instanceof TextView){
//						jacksonEntry = jacksonTable.getEntry(columnIndex, rowIndex);
//					}
//				}
				if(jacksonEntry != null) {
					String content = jacksonEntry.getContent();
					itemList[rowIndex][columnIndex-1] = content;
				}
			}
		}
		ExpandableListView expListView = (ExpandableListView) mainView.findViewById(R.id.exp_table_list_view);
        final ExpandableListAdapter expListAdapter = new CustomExpandableListAdapter(
                getActivity(), groupList, itemList);
        expListView.setAdapter(expListAdapter);
	}
	
	protected void setTypeContents(TableLayout dialogTable){
		Log.d("TableFragment", "setTypeContents");
		final int jsonOldNumberOfColumns = jacksonTable.getNumberOfColumns();
		for(int i=1; i<dialogTable.getChildCount(); i++){
			int indexOfTable = i-1;
			TableRow dialogTableRow = (TableRow) dialogTable.getChildAt(i);
			final Spinner spin = (Spinner) dialogTableRow.getChildAt(2);
			final String choice = spin.getSelectedItem().toString();
			//
			// JSON START
			// check index
			if(indexOfTable > jsonOldNumberOfColumns) {
				// we have to create a new column
				if(choice.equals("Textfeld")){
					jacksonTable.addColumn(new ColumnHeader("", StringClass.TYPE_STRING));
				}
				else if(choice.equals("CheckBox")){
					jacksonTable.addColumn(new ColumnHeader("", CheckBoxClass.TYPE_STRING));
				}
				else if(choice.equals("PopUp")){
					jacksonTable.addColumn(new ColumnHeader("", PopupClass.TYPE_STRING));
				}
			}
			else {
				// we have to change the type
				// change column type in json
				if(choice.equals("Textfeld")){
					jacksonTable.changeColumnType(indexOfTable, StringClass.TYPE_STRING);
				}
				else if(choice.equals("CheckBox")){
					jacksonTable.changeColumnType(indexOfTable, CheckBoxClass.TYPE_STRING);
				}
				else if(choice.equals("PopUp")){
					jacksonTable.changeColumnType(indexOfTable, PopupClass.TYPE_STRING);
				}				
			}
			// JSON END
			//
			for(int k=0; k<table.getChildCount(); k++){
				boolean isModified = false;
				View newElement = null;
				final TableRow tableRow = (TableRow) table.getChildAt(k);
				View elementToAdapt = tableRow.getChildAt(indexOfTable);
				// moved before jackson part above
//				Spinner spin = (Spinner) dialogTableRow.getChildAt(2);
//				String choice = spin.getSelectedItem().toString();
				if(choice.equals("Textfeld")){
					if(!(elementToAdapt instanceof EditText)){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initEditText(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
					}
				}
				else if(choice.equals("CheckBox")){
					if(!(elementToAdapt instanceof LinearLayout)){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initCheckBox(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
						Log.d("TABLE_FRAGMENT", "FFFFFFFFF");
					}
					else if(!(((LinearLayout) elementToAdapt).getChildAt(0) instanceof CheckBox)){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initCheckBox(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
						Log.d("TABLE_FRAGMENT", "GGGGGGGGGG");
					}
				}
				else if(choice.equals("PopUp")){
					if(!(elementToAdapt instanceof TextView) || elementToAdapt instanceof EditText){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initPopup(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
					}
					else if(((LinearLayout) elementToAdapt).getChildAt(0) instanceof CheckBox){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initPopup(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
					}
				}
				if(isModified){
					newElement.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					int width = newElement.getMeasuredWidth();
					int height = newElement.getMeasuredHeight();
					checkResize(width, height, newElement, tableRow);
//					int width = getNeededWidth(i);
//					int height = getNeededHeight(0, tableRow);
//					final LayoutParams lparams = new LayoutParams(width, height);
//				    newElement.setLayoutParams(lparams);
				}
			}
		}
	}
	
	/**
	 * adapts the header table to match the caption of the given dialogTable
	 * @param dialogTable
	 */
	protected void adaptHeaderTable(TableLayout dialogTable){
		int amountRows = dialogTable.getChildCount()-1;
		for(int i=1; i<amountRows+1; i++){
			String otherString = ((EditText) ((TableRow) dialogTable.getChildAt(i)).getChildAt(1)).getText().toString();
			EditText textToChange = ((EditText) ((TableRow) headerTable.getChildAt(0)).getChildAt(i-1));
			if(!otherString.equals("")){
				textToChange.setText(otherString);
			}
		}
	}
	
	protected TableLayout createTableHeader() {
		headerTable = (TableLayout) mainView.findViewById(R.id.header_table);
		final TableRow row = new TableRow(getActivity());
		TableRow.LayoutParams rowParams = new TableRow.LayoutParams();
		// Wrap-up the content of the row
		rowParams.height = TableRow.LayoutParams.MATCH_PARENT;
		rowParams.width = TableRow.LayoutParams.MATCH_PARENT;
		TableRow.LayoutParams colParams = new TableRow.LayoutParams();
		colParams.height = TableRow.LayoutParams.MATCH_PARENT;
		colParams.width = TableRow.LayoutParams.MATCH_PARENT;
		headerTable.addView(row);
		jacksonLoadTableHeader(row);
		return headerTable;
	}
	
	
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		if(v instanceof TableRow){
			contextMenuRow = (TableRow) v;
		}
		MenuInflater inflater = SlideoutNavigationActivity.theActiveActivity.getMenuInflater();
		inflater.inflate(R.menu.template_generator_remove_table_item, menu);
	}
	
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.removeTableRow:
			removeRow(contextMenuRow);
			return true;
		default:
			return super.onContextItemSelected(item);
		}
	}
	
	/**
	 * removes one row of the table
	 * @param row
	 */
	protected void removeRow(TableRow row) {
		if(table.getChildCount() <= 1) {
			return;
		}
		// JACKSON
		if(!jacksonInflateWithData) {
			jacksonTable.removeRow(table.indexOfChild(row));
		}
		// JACKSON END
        table.removeView(row);
	}

	/**
	 * adds a new row to the table
	 */
	protected void addItemList() {
			//
			// JACKSON
			// create jackson row first, so we can use it in addColumnToRow
        	if(!jacksonInflateWithData) {
        		jacksonTable.addNewRow();
        	}
        	//
        	// JACKSON END
        	//
	        TableRow row = new TableRow(getActivity());
	        registerForContextMenu(row);
	        table.addView(row);
	        for(int i=0; i<amountColumns; ++i){
	        	addColumnToRow(row);
	        }
//	        table.addView(row);
	        final ScrollView sv = (ScrollView) mainView.findViewById(R.id.table_scroll);
	        //note: we have to do scrolling in seperate thread to make sure the new item is already inserted
	        sv.post(new Runnable() {
	            @Override
	            public void run() {
	            	sv.fullScroll(ScrollView.FOCUS_DOWN);
	            }
	        });
	        for(int i=0; i<((TableRow) headerTable.getChildAt(0)).getChildCount(); i++){
	        	setHeaderTableStyle((EditText) ((TableRow) headerTable.getChildAt(0)).getChildAt(i));
	        }
	}

	/**
	 * @param columnIndex
	 * @return width of biggest element in column with given columnIndex
	 */
	private int getNeededWidth(int columnIndex) {
		int longestWidth = -1;
		for (int i = 0; i < headerTable.getChildCount(); i++) {
			View child = headerTable.getChildAt(i);
			TableRow oneRow = (TableRow) child;
			if (child instanceof TableRow) {
				View view = oneRow.getChildAt(columnIndex);
				if(view != null){
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					int elementSize = view.getMeasuredWidth();
					if(elementSize > longestWidth){
						longestWidth = elementSize;
					}
				}
			}
		}
		for (int i = 0; i < table.getChildCount(); i++) {
			View child = table.getChildAt(i);
			TableRow oneRow = (TableRow) child;
			if (child instanceof TableRow) {
				View view = oneRow.getChildAt(columnIndex);
				if(view != null){
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					int elementSize = view.getMeasuredWidth();
					if(elementSize > longestWidth){
						longestWidth = elementSize;
					}
				}
			}
		}
		return longestWidth;
	}
	
	/**
	 * 
	 * @param rowIndex
	 * @param row
	 * @return height of biggest element in column with given rowIndex
	 */
	private int getNeededHeight(int rowIndex, TableRow row) {
		int maxHeight = -1;
		for (int i = 0; i < row.getChildCount(); i++) {
			View child = row.getChildAt(i);
			if(child != null){
				child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
				int elementSize = child.getMeasuredHeight();
				if(elementSize > maxHeight){
					maxHeight = elementSize;
				}
			}
		}
		return maxHeight;
	}
	
	/**
	 * checks if it is needed to resize the given row (does it if textEdited is bigger now)
	 * @param width
	 * @param height
	 * @param textEdited
	 * @param row
	 */
	protected void checkResize(int width, int height, View textEdited, TableRow row){
		TableLayout usedTable;
		usedTable = table;
		int indexOfRow = table.indexOfChild(row);
		if(indexOfRow == -1){
			indexOfRow = headerTable.indexOfChild(row);
			if(indexOfRow == -1){
				Log.d("critical", "table to search for element not known!");
			}
			else{
				usedTable = headerTable;
			}
		}
//		Log.d("index", "indexOfRow  == " + indexOfRow);
		int indexOfColumn = -1;
		if(usedTable.getChildAt(indexOfRow) instanceof TableRow){
			indexOfColumn = ((TableRow) usedTable.getChildAt(indexOfRow)).indexOfChild(textEdited);
		}
//		Log.d("index", "indexOfColumn  == " + indexOfColumn);
		int largestWidth = 0;
		//traverse over all columns to get biggest width
		//first columns of normal table
		for (int i = 0; i < table.getChildCount(); i++) {
			View child = table.getChildAt(i);
			TableRow oneRow = (TableRow) child;
			if (child instanceof TableRow) {
				View view = oneRow.getChildAt(indexOfColumn);
				if(view != null){
					int localWidth = 0;
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					localWidth = view.getMeasuredWidth();
					if(localWidth > largestWidth){
						largestWidth = localWidth;
					}
				}
			}
		}
		//than compare with header table also
		for (int i = 0; i < headerTable.getChildCount(); i++) {
			View child = headerTable.getChildAt(i);
			TableRow oneRow = (TableRow) child;
			if (child instanceof TableRow) {
				View view = oneRow.getChildAt(indexOfColumn);
				int localWidth = 0;
				if(view != null){
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					localWidth = view.getMeasuredWidth();
					if(localWidth > largestWidth){
						largestWidth = localWidth;
					}
				}
			}
		}
		/* Code that measures the height of one row
		int largestHeight = 0;
		if (row instanceof TableRow) {
			for(int i=0; i<((TableRow) row).getChildCount(); i++){
				View view = ((TableRow) row).getChildAt(i);
				int localHeight = 0;
				if(view instanceof EditText){
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					localHeight = view.getMeasuredHeight();
					if(localHeight > largestHeight){
						largestHeight = localHeight;
					}
				}
			}
		}
		*/
		adaptAllColumnsToSize(indexOfColumn, largestWidth);
	}
	
	/**
	 * adapts all columns of the table with given columnIndex to the given width
	 * @param columnIndex
	 * @param width
	 */
	protected void adaptAllColumnsToSize(int columnIndex, int width){
		View singleRow = headerTable.getChildAt(0);
		if(singleRow instanceof TableRow){
			View theChildToResize = ((TableRow) singleRow).getChildAt(columnIndex);
			if(theChildToResize != null){
//				setHeaderTableStyle((EditText) theChildToResize);
				theChildToResize.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
				final TableRow.LayoutParams lparams = new TableRow.LayoutParams(width,getNeededHeight(0, ((TableRow) singleRow))); // Width , height
			    theChildToResize.setLayoutParams(lparams);
			}
		}
		for(int i=0; i<table.getChildCount(); i++){
			View oneRow = table.getChildAt(i);
			if(oneRow instanceof TableRow){
				View theChildToResize = ((TableRow) oneRow).getChildAt(columnIndex);
				if(theChildToResize != null){
					theChildToResize.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					final TableRow.LayoutParams lparams = new TableRow.LayoutParams(width, getNeededHeight(i, ((TableRow) oneRow))); // Width , height
				    theChildToResize.setLayoutParams(lparams);
				}
				
			}
		}
	}
	
	/**
	 * changes amount of table columns to the given amountOfColumns
	 * @param amountOfColumns
	 */
	protected void setAmountOfColumns(int amountOfColumns){
		int amountToAdd = amountOfColumns - amountColumns;
		if(amountToAdd > 0){
			for(int i=0; i<amountToAdd; i++){
				addColumn();
			}
		}
		else{
			for(int i=amountToAdd; i<0; i++){
				removeColumn();
			}
		}
	}
	
	private EditText initEditText(final TableRow row, final IEditableContent jacksonEntry){
//		Log.d("initEditText", "jacksonEntry:"+jacksonEntry.hashCode());
		final EditText newElement = new EditText(getActivity());
		newElement.setGravity(Gravity.CENTER);
		newElement.addTextChangedListener(new TextWatcher(){
			public void afterTextChanged(Editable s) {
				checkResize(0, 0, newElement, row);
			}
			public void beforeTextChanged(CharSequence s, int start, int count, int after){
			}
			public void onTextChanged(CharSequence s, int start, int before, int count){
			}
		});
		if(row == headerTable.getChildAt(0)) {
			setHeaderTableStyle((EditText) newElement);
		}
		else {
			setTableStyle(newElement);
		}
		//
		// JACKSON START
		//
		if(jacksonEntry != null) {
			newElement.setText(jacksonEntry.getContent());
			newElement.addTextChangedListener(new TextWatcher() {
				private final IEditableContent content = jacksonEntry;
				public void afterTextChanged(Editable s) {
					// guard. only set new content if we are not currently inflating with data.
					if(!jacksonInflateWithData) {
						content.setContent(s.toString());
					}
					checkResize(0, 0, newElement, row);
				}
				public void beforeTextChanged(CharSequence s, int start, int count, int after){
				}
				public void onTextChanged(CharSequence s, int start, int before, int count){
				}
			});
		}
		//
		// JACKSON END
		//
		// we can do it like this with a check, or we change the default value in jackson model
		// check is needed, because we would otherwise overwrite the loaded value
		if(newElement.getText().toString().isEmpty()) {
			if(row == headerTable.getChildAt(0)) {
				newElement.setText(getResources().getString(R.string.headline)
								+ " "
								+ (((TableRow) headerTable.getChildAt(0))
										.getChildCount()+1));
			}	
			else {
				((EditText) newElement).setText(getResources().getString(R.string.blank));
			}
		}
//		((EditText) newElement).clearFocus();
//		setTableStyle(newElement);
		return newElement;
	}
	
    int styleStart = 0;
    int cursorLoc = 0;
    
    private ArrayList<String> getAllElementsToRef(FolderFragment fragmentToSearch){
    	ArrayList<String> results = new ArrayList<String>();
		Log.d("popupReferences", "subdirs: " + fragmentToSearch.dataAdapter.getAll().length);
        for(FolderElementData currentDatum  : fragmentToSearch.dataAdapter.getAll()){
        	GeneralFragment currentFragment = currentDatum.childFragment;
        	if(currentFragment instanceof FolderFragment){
    			Log.d("popupReferences", "folderfragment found, descending now");
        		ArrayList<String> toAdd = getAllElementsToRef((FolderFragment) currentFragment);
        		results.addAll(toAdd);
        	}
        	else if(currentFragment instanceof TableFragment){
    			Log.d("popupReferences", "tableview found");
        	}
        	else if(currentFragment instanceof MatrixFragment){
    			Log.d("popupReferences", "matrix found. Elements:" + (((MatrixFragment) currentFragment).itemsList).size());
        		for(MatrixItem oneItem : ((MatrixFragment) currentFragment).itemsList){
        			String oneName = oneItem.getItemName();
        			results.add(oneName);
        		}
        	}
        	else{
    			Log.d("popupReferences", "unhandled element found!!!");
        	}
        }
        return results;
    }
	
    private LinearLayout initPopup(final TableRow row, final IEditableContent jacksonEntry){
		Log.d("TABLE_FRAGMENT", "init_popup");

		final LinearLayout ll = new LinearLayout(getActivity());
		final TextView newElement = new TextView(getActivity());
		//
		// JACKSON START
		//
		//temporarily disabled, have to take a closer look to popups
//		if(jacksonEntry != null) {
//			newElement.setText(jacksonEntry.toString());
//			newElement.addTextChangedListener(new TextWatcher() {
//				final IEditableContent myJacksonEntry = jacksonEntry;
//				// callback
//				public void afterTextChanged(Editable s) {
//					// guard. only set column title if we are not currently inflating with data
//					if(!jacksonInflateWithData) {
//						myJacksonEntry.setContent(s.toString());
//					}
//				}
//				public void beforeTextChanged(CharSequence s, int start, int count, int after){
//				}
//				public void onTextChanged(CharSequence s, int start, int before, int count){
//				}
//			});
//		}
		//
		// JACKSON END
		//
		final TextView txt = (TextView) newElement;
		txt.addTextChangedListener(new TextWatcher(){
			public void afterTextChanged(Editable s) {
				checkResize(0, 0, txt, row);
			}
			public void beforeTextChanged(CharSequence s, int start, int count, int after){
			}
			public void onTextChanged(CharSequence s, int start, int before, int count){
			}
		});
        LayoutInflater inflater = (LayoutInflater) SlideoutNavigationActivity.theActiveActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final View popupView = inflater.inflate(R.layout.table_view_popup, null);

//        final View layoutContainingHeadline = (View) popupView.findViewById(R.id.popup_content);
        final TextView popupHeadline = (TextView) popupView.findViewById(R.id.popup_headline);
        popupHeadline.setText(((SlideoutNavigationActivity) SlideoutNavigationActivity.theActiveActivity).getCurrentFragment().elementName);
        final EditText inputPopup = (EditText) popupView.findViewById(R.id.popup_editText);
        
        
        
        final ToggleButton toggleBold = (ToggleButton) popupView.findViewById(R.id.toggle_bold);
        toggleBold.setOnClickListener(new Button.OnClickListener() {
        	public void onClick(View v) {
        		int selectionStart = inputPopup.getSelectionStart();
        		styleStart = selectionStart;
        		// following code might be needed if they fix this bug: 
        		// http://code.google.com/p/android/issues/detail?id=62508
        		//but atm text marking in popupwindow doesnt work so we don't need to deal with 
        		//selectionEnd != selectionStart
        		/*
                int selectionEnd = inputPopup.getSelectionEnd();
                if (selectionStart > selectionEnd){
                    int temp = selectionEnd;
                    selectionEnd = selectionStart;
                    selectionStart = temp;
                }
                if (selectionEnd > selectionStart)
                {
                    Spannable str = inputPopup.getText();
                    StyleSpan[] ss = str.getSpans(selectionStart, selectionEnd, StyleSpan.class);

                    boolean exists = false;
                    for (int i = 0; i < ss.length; i++) {
                        if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
                            str.removeSpan(ss[i]);
                            exists = true;
                        }
                    }
                    if (!exists){
                        str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    toggleBold.setChecked(false);
                }
        		 */
        	}
        });
        final ToggleButton toggleItalic = (ToggleButton) popupView.findViewById(R.id.toggle_italic);
        toggleItalic.setOnClickListener(new Button.OnClickListener() {
        	public void onClick(View v) {
        		int selectionStart = inputPopup.getSelectionStart();
        		styleStart = selectionStart;
        	}
        });
        final ToggleButton toggleUnderlined = (ToggleButton) popupView.findViewById(R.id.toggle_underline);
        toggleUnderlined.setPaintFlags(Paint.UNDERLINE_TEXT_FLAG);
        toggleUnderlined.setOnClickListener(new Button.OnClickListener() {
        	public void onClick(View v) {
        		int selectionStart = inputPopup.getSelectionStart();
        		styleStart = selectionStart;
        	}
        });
        
        
        inputPopup.addTextChangedListener(new TextWatcher() { 
        	public void afterTextChanged(Editable s) { 
        		int position = Selection.getSelectionStart(inputPopup.getText());
        		if (position < 0){
        			position = 0;
        		}
        		if (position > 0){
        			if (styleStart > position || position > (cursorLoc + 1)){
        				//user changed cursor location, reset
        				styleStart = position - 1;
        			}
        			cursorLoc = position;
//            		Log.d("textstyle", "styleStart == " + styleStart + ", position == " + position);
        			if (toggleBold.isChecked()){
                        StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);
                        for (int i = 0; i < ss.length; i++) {
                            if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
                                s.removeSpan(ss[i]);
                            }
                        }
                        s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    if (toggleItalic.isChecked()){
                        StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);
                        for (int i = 0; i < ss.length; i++) {
                            if (ss[i].getStyle() == android.graphics.Typeface.ITALIC){
                                s.removeSpan(ss[i]);
                            }
                        }
                        s.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    if (toggleUnderlined.isChecked()){
                    	UnderlineSpan[] ss = s.getSpans(styleStart, position, UnderlineSpan.class);
                        for (int i = 0; i < ss.length; i++) {
                                s.removeSpan(ss[i]);
                        }
                        s.setSpan(new UnderlineSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    inputPopup.setText(s);
                    inputPopup.setSelection(position);
        		}
        			
        	}
        	public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
        		//unused
        	} 
        	public void onTextChanged(CharSequence s, int start, int before, int count) { 
        		
        	} 
        });
        
        
        //before
//        toggleBold.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
//            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//                if (isChecked) {
//                	if(toggleItalic.isChecked()){
////                		inputPopup.setTextAppearance(getActivity(), R.style.italic_bold);
//                		inputPopup.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD_ITALIC));
//                	}
//                	else{
//                		inputPopup.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
//                	}
//                } else {
//                	if(toggleItalic.isChecked()){
////                		inputPopup.setTextAppearance(getActivity(), R.style.italic);
//                		inputPopup.setTypeface(Typeface.defaultFromStyle(Typeface.ITALIC));
//                	}
//                	else{
////                		inputPopup.setTextAppearance(getActivity(), R.style.normal_text);
//                		inputPopup.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
//                	}
//                }
//            }
//        });
        
        DisplayMetrics displayMetrics = getActivity().getResources().getDisplayMetrics();
//        float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
        float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
//        int popupHeight = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, getResources().getDimension(R.dimen.popup_height), getResources().getDisplayMetrics()));
//        int popupWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, getResources().getDimension(R.dimen.popup_width), getResources().getDisplayMetrics()));
//		int popupHeight = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) (dpHeight*0.8), getResources().getDisplayMetrics()));<commit_msg>popup content is now saved and loaded<commit_after>package de.fau.cs.mad.gamekobold.template_generator;



import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;

import de.fau.cs.mad.gamekobold.R;
import de.fau.cs.mad.gamekobold.SlideoutNavigationActivity;
import de.fau.cs.mad.gamekobold.character.CharacterEditActivity;
import de.fau.cs.mad.gamekobold.character.CustomExpandableListAdapter;
import de.fau.cs.mad.gamekobold.jackson.CheckBoxClass;
import de.fau.cs.mad.gamekobold.jackson.ColumnHeader;
import de.fau.cs.mad.gamekobold.jackson.IEditableContent;
import de.fau.cs.mad.gamekobold.jackson.PopupClass;
import de.fau.cs.mad.gamekobold.jackson.StringClass;
import de.fau.cs.mad.gamekobold.jackson.Table;
import de.fau.cs.mad.gamekobold.matrix.MatrixFragment;
import de.fau.cs.mad.gamekobold.matrix.MatrixItem;
import de.fau.cs.mad.gamekobold.template_generator.SessionMonitorEditText.OnEditSessionCompleteListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.text.Editable;
import android.support.v4.app.Fragment;
import android.support.v4.app.DialogFragment;
import android.support.v4.widget.SearchViewCompat;
import android.text.Selection;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.PopupWindow.OnDismissListener;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TableRow.LayoutParams;
import android.widget.TextView;
import android.widget.ToggleButton;

@SuppressLint("NewApi")
public class TableFragment extends GeneralFragment implements OnCheckedChangeListener{
	/*
	 * JACKSON START
	 */
	Table jacksonTable;
	boolean jacksonInflateWithData = false;
	/*
	 * JACKSON END
	 */
	
	enum content_type{
		editText, checkbox, popup;
	}
	
	View mainView;
	TableLayout table;
	TableLayout headerTable;
	// also set in createTableHeader !! onCreate is called when orientation is rotated ->
	// amountColumns = #before change but we recreate the header table with 2 columns
	int amountColumns = 2;
//	AlertDialog dialog;
//	TableLayout dialogTable;
	SessionMonitorEditText dialogRowCounter = null;
	//menu shown when long clicking a row
	protected TableRow contextMenuRow;
//	protected ArrayList<View> popupViewList = new ArrayList<>();
//	protected ArrayList<PopupWindow> popupList = new ArrayList<>();


	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);   
        setRetainInstance(true);
    	LayoutInflater inflater = (LayoutInflater) SlideoutNavigationActivity.theActiveActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if(SlideoutNavigationActivity.theActiveActivity instanceof TemplateGeneratorActivity){
//			Log.d("TableFragment", "inflated for TemplateGenerator");
        	//create the table that will be shown in the dialog
        	mainView = (RelativeLayout) inflater.inflate(R.layout.template_generator_table_view, new LinearLayout(getActivity()), false);
        	table = (TableLayout) mainView.findViewById(R.id.template_generator_table);
        	createTableHeader();
        	//set the 3 buttons
        	Button buttonAdd = (Button)mainView.findViewById(R.id.add_row);
        	buttonAdd.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
        			addItemList();
        		}
        	});
        	Button addColumnButton = (Button)mainView.findViewById(R.id.add_column);
        	addColumnButton.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
        			addColumn();
        		}
        	});
        	Button removeColumnButton = (Button)mainView.findViewById(R.id.remove_column);
        	removeColumnButton.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
        			removeColumn();
        		}
        	});
        	TextView addRowBelow = (TextView)mainView.findViewById(R.id.add_below);
        	addRowBelow.setOnClickListener(new View.OnClickListener() {
        		public void onClick(View v) {
        			addItemList();
        		}
        	});
        	setAddButtonStyle(addRowBelow);
        }
        else if(SlideoutNavigationActivity.theActiveActivity instanceof CharacterEditActivity){
			Log.d("TableFragment", "inflated for CharacterEditActivity");
        	mainView = (RelativeLayout) inflater.inflate(R.layout.character_edit_table_view, new LinearLayout(getActivity()), false);
        }
		// removed because we could otherwise not save/load tables with 0 rows
		//addItemList();
    }
	
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
		super.onCreateView(inflater, container, savedInstanceState);
		// JACKSON START
		if(SlideoutNavigationActivity.theActiveActivity instanceof TemplateGeneratorActivity){
			// check for saved rows
			table.removeAllViews();
			if(jacksonTable.getRowCount() > 0) {
				jacksonInflateWithData = true;
				// adjust row count
				final int jacksonRowNum = jacksonTable.getRowCount();
				while(table.getChildCount() < jacksonRowNum) {
					// TODO hier die rows laden
//					addItemList();
					final int columnCount = jacksonTable.getNumberOfColumns();
			        final TableRow row = new TableRow(getActivity());
			        registerForContextMenu(row);
					for(int i = 0 ; i < columnCount; i++) {
						final int rowIndex = table.getChildCount();
						final ColumnHeader header = jacksonTable.getColumnHeader(i);
						View newElement;
						if(header.isString()) {
							newElement = initEditText(row, jacksonTable.getEntry(i, rowIndex));
						}
						else if(header.isCheckBox()) {
							newElement = initCheckBox(row, jacksonTable.getEntry(i, rowIndex));
						}
						else {
							newElement = initPopup(row, jacksonTable.getEntry(i, rowIndex));
						}
						row.addView(newElement);
					}
			        table.addView(row);
					Log.d("TableFragment", "added row");
				}
				while(table.getChildCount() > jacksonRowNum) {
					removeRow((TableRow)table.getChildAt(table.getChildCount()-1));
					Log.d("TableFragment", "removed row");
				}
				jacksonInflateWithData = false;
			}
			else {
				addItemList();
			}
		}
		else if(SlideoutNavigationActivity.theActiveActivity instanceof CharacterEditActivity){
			// check for saved rows
			fillListView();
		}
		//
		// JACKSON END
		//
		return mainView;
	}
	
	
	private void fillListView(){
		final int jacksonTableColumnNumber = jacksonTable.getNumberOfColumns();
		final int jacksonRowNum = jacksonTable.getRowCount();

		// check if we got any saved columns (they are only created if user goes into table!)
		// so if there are no saved columns or we didn't load any data we add the default columns 
		
//		jacksonTable.getEntry(columnIndex, rowIndex)
//		List<String> your_array_list = new ArrayList<String>();
//        your_array_list.add("foo");
//		ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
//                this, 
//                android.R.layout.simple_list_item_1,
//                your_array_list );
		String[] groupList = new String[jacksonRowNum];
		String[][] itemList = new String[jacksonRowNum][];
		for(int rowIndex=0; rowIndex<jacksonRowNum; rowIndex++){
			groupList[rowIndex] = jacksonTable.getEntry(0, rowIndex).getContent();
		}
		
		for(int rowIndex=0; rowIndex<jacksonRowNum; rowIndex++){
			itemList[rowIndex] = new String[jacksonTableColumnNumber-1];
			for(int columnIndex=1; columnIndex<jacksonTableColumnNumber; columnIndex++){
//				View firstRowView = null;
				//TODO: get saved table type from jackson here
				//now just assume it is edittext
//				TableRow firstRow = (TableRow) table.getChildAt(0);
				IEditableContent jacksonEntry = null;
				jacksonEntry = jacksonTable.getEntry(columnIndex, rowIndex);
//				if(firstRow != null){
//					firstRowView = firstRow.getChildAt(columnIndex);
//				}
//				if(firstRowView instanceof EditText){
//					jacksonEntry = jacksonTable.getEntry(columnIndex, rowIndex);
//				}
//				else if(firstRowView instanceof LinearLayout){
//					if(((LinearLayout) firstRowView).getChildAt(0) instanceof CheckBox){
//						jacksonEntry = jacksonTable.getEntry(columnIndex, rowIndex);
//					}
//					else{// if(((LinearLayout) firstRowView).getChildAt(0) instanceof TextView){
//						jacksonEntry = jacksonTable.getEntry(columnIndex, rowIndex);
//					}
//				}
				if(jacksonEntry != null) {
					String content = jacksonEntry.getContent();
					itemList[rowIndex][columnIndex-1] = content;
				}
			}
		}
		ExpandableListView expListView = (ExpandableListView) mainView.findViewById(R.id.exp_table_list_view);
        final ExpandableListAdapter expListAdapter = new CustomExpandableListAdapter(
                getActivity(), groupList, itemList);
        expListView.setAdapter(expListAdapter);
	}
	
	protected void setTypeContents(TableLayout dialogTable){
		Log.d("TableFragment", "setTypeContents");
		final int jsonOldNumberOfColumns = jacksonTable.getNumberOfColumns();
		for(int i=1; i<dialogTable.getChildCount(); i++){
			int indexOfTable = i-1;
			TableRow dialogTableRow = (TableRow) dialogTable.getChildAt(i);
			final Spinner spin = (Spinner) dialogTableRow.getChildAt(2);
			final String choice = spin.getSelectedItem().toString();
			//
			// JSON START
			// check index
			if(indexOfTable > jsonOldNumberOfColumns) {
				// we have to create a new column
				if(choice.equals("Textfeld")){
					jacksonTable.addColumn(new ColumnHeader("", StringClass.TYPE_STRING));
				}
				else if(choice.equals("CheckBox")){
					jacksonTable.addColumn(new ColumnHeader("", CheckBoxClass.TYPE_STRING));
				}
				else if(choice.equals("PopUp")){
					jacksonTable.addColumn(new ColumnHeader("", PopupClass.TYPE_STRING));
				}
			}
			else {
				// we have to change the type
				// change column type in json
				if(choice.equals("Textfeld")){
					jacksonTable.changeColumnType(indexOfTable, StringClass.TYPE_STRING);
				}
				else if(choice.equals("CheckBox")){
					jacksonTable.changeColumnType(indexOfTable, CheckBoxClass.TYPE_STRING);
				}
				else if(choice.equals("PopUp")){
					jacksonTable.changeColumnType(indexOfTable, PopupClass.TYPE_STRING);
				}				
			}
			// JSON END
			//
			for(int k=0; k<table.getChildCount(); k++){
				boolean isModified = false;
				View newElement = null;
				final TableRow tableRow = (TableRow) table.getChildAt(k);
				View elementToAdapt = tableRow.getChildAt(indexOfTable);
				// moved before jackson part above
//				Spinner spin = (Spinner) dialogTableRow.getChildAt(2);
//				String choice = spin.getSelectedItem().toString();
				if(choice.equals("Textfeld")){
					if(!(elementToAdapt instanceof EditText)){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initEditText(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
					}
				}
				else if(choice.equals("CheckBox")){
					if(!(elementToAdapt instanceof LinearLayout)){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initCheckBox(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
						Log.d("TABLE_FRAGMENT", "FFFFFFFFF");
					}
					else if(!(((LinearLayout) elementToAdapt).getChildAt(0) instanceof CheckBox)){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initCheckBox(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
						Log.d("TABLE_FRAGMENT", "GGGGGGGGGG");
					}
				}
				else if(choice.equals("PopUp")){
					if(!(elementToAdapt instanceof TextView) || elementToAdapt instanceof EditText){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initPopup(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
					}
					else if(((LinearLayout) elementToAdapt).getChildAt(0) instanceof CheckBox){
						isModified = true;
						tableRow.removeView(elementToAdapt);
						newElement = initPopup(tableRow, jacksonTable.getEntry(indexOfTable, k));
						tableRow.addView(newElement, indexOfTable);
					}
				}
				if(isModified){
					newElement.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					int width = newElement.getMeasuredWidth();
					int height = newElement.getMeasuredHeight();
					checkResize(width, height, newElement, tableRow);
//					int width = getNeededWidth(i);
//					int height = getNeededHeight(0, tableRow);
//					final LayoutParams lparams = new LayoutParams(width, height);
//				    newElement.setLayoutParams(lparams);
				}
			}
		}
	}
	
	/**
	 * adapts the header table to match the caption of the given dialogTable
	 * @param dialogTable
	 */
	protected void adaptHeaderTable(TableLayout dialogTable){
		int amountRows = dialogTable.getChildCount()-1;
		for(int i=1; i<amountRows+1; i++){
			String otherString = ((EditText) ((TableRow) dialogTable.getChildAt(i)).getChildAt(1)).getText().toString();
			EditText textToChange = ((EditText) ((TableRow) headerTable.getChildAt(0)).getChildAt(i-1));
			if(!otherString.equals("")){
				textToChange.setText(otherString);
			}
		}
	}
	
	protected TableLayout createTableHeader() {
		headerTable = (TableLayout) mainView.findViewById(R.id.header_table);
		final TableRow row = new TableRow(getActivity());
		TableRow.LayoutParams rowParams = new TableRow.LayoutParams();
		// Wrap-up the content of the row
		rowParams.height = TableRow.LayoutParams.MATCH_PARENT;
		rowParams.width = TableRow.LayoutParams.MATCH_PARENT;
		TableRow.LayoutParams colParams = new TableRow.LayoutParams();
		colParams.height = TableRow.LayoutParams.MATCH_PARENT;
		colParams.width = TableRow.LayoutParams.MATCH_PARENT;
		headerTable.addView(row);
		jacksonLoadTableHeader(row);
		return headerTable;
	}
	
	
	public void onCreateContextMenu(ContextMenu menu, View v,
			ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		if(v instanceof TableRow){
			contextMenuRow = (TableRow) v;
		}
		MenuInflater inflater = SlideoutNavigationActivity.theActiveActivity.getMenuInflater();
		inflater.inflate(R.menu.template_generator_remove_table_item, menu);
	}
	
	public boolean onContextItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.removeTableRow:
			removeRow(contextMenuRow);
			return true;
		default:
			return super.onContextItemSelected(item);
		}
	}
	
	/**
	 * removes one row of the table
	 * @param row
	 */
	protected void removeRow(TableRow row) {
		if(table.getChildCount() <= 1) {
			return;
		}
		// JACKSON
		if(!jacksonInflateWithData) {
			jacksonTable.removeRow(table.indexOfChild(row));
		}
		// JACKSON END
        table.removeView(row);
	}

	/**
	 * adds a new row to the table
	 */
	protected void addItemList() {
			//
			// JACKSON
			// create jackson row first, so we can use it in addColumnToRow
        	if(!jacksonInflateWithData) {
        		jacksonTable.addNewRow();
        	}
        	//
        	// JACKSON END
        	//
	        TableRow row = new TableRow(getActivity());
	        registerForContextMenu(row);
	        table.addView(row);
	        for(int i=0; i<amountColumns; ++i){
	        	addColumnToRow(row);
	        }
//	        table.addView(row);
	        final ScrollView sv = (ScrollView) mainView.findViewById(R.id.table_scroll);
	        //note: we have to do scrolling in seperate thread to make sure the new item is already inserted
	        sv.post(new Runnable() {
	            @Override
	            public void run() {
	            	sv.fullScroll(ScrollView.FOCUS_DOWN);
	            }
	        });
	        for(int i=0; i<((TableRow) headerTable.getChildAt(0)).getChildCount(); i++){
	        	setHeaderTableStyle((EditText) ((TableRow) headerTable.getChildAt(0)).getChildAt(i));
	        }
	}

	/**
	 * @param columnIndex
	 * @return width of biggest element in column with given columnIndex
	 */
	private int getNeededWidth(int columnIndex) {
		int longestWidth = -1;
		for (int i = 0; i < headerTable.getChildCount(); i++) {
			View child = headerTable.getChildAt(i);
			TableRow oneRow = (TableRow) child;
			if (child instanceof TableRow) {
				View view = oneRow.getChildAt(columnIndex);
				if(view != null){
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					int elementSize = view.getMeasuredWidth();
					if(elementSize > longestWidth){
						longestWidth = elementSize;
					}
				}
			}
		}
		for (int i = 0; i < table.getChildCount(); i++) {
			View child = table.getChildAt(i);
			TableRow oneRow = (TableRow) child;
			if (child instanceof TableRow) {
				View view = oneRow.getChildAt(columnIndex);
				if(view != null){
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					int elementSize = view.getMeasuredWidth();
					if(elementSize > longestWidth){
						longestWidth = elementSize;
					}
				}
			}
		}
		return longestWidth;
	}
	
	/**
	 * 
	 * @param rowIndex
	 * @param row
	 * @return height of biggest element in column with given rowIndex
	 */
	private int getNeededHeight(int rowIndex, TableRow row) {
		int maxHeight = -1;
		for (int i = 0; i < row.getChildCount(); i++) {
			View child = row.getChildAt(i);
			if(child != null){
				child.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
				int elementSize = child.getMeasuredHeight();
				if(elementSize > maxHeight){
					maxHeight = elementSize;
				}
			}
		}
		return maxHeight;
	}
	
	/**
	 * checks if it is needed to resize the given row (does it if textEdited is bigger now)
	 * @param width
	 * @param height
	 * @param textEdited
	 * @param row
	 */
	protected void checkResize(int width, int height, View textEdited, TableRow row){
		TableLayout usedTable;
		usedTable = table;
		int indexOfRow = table.indexOfChild(row);
		if(indexOfRow == -1){
			indexOfRow = headerTable.indexOfChild(row);
			if(indexOfRow == -1){
				Log.d("critical", "table to search for element not known!");
			}
			else{
				usedTable = headerTable;
			}
		}
//		Log.d("index", "indexOfRow  == " + indexOfRow);
		int indexOfColumn = -1;
		if(usedTable.getChildAt(indexOfRow) instanceof TableRow){
			indexOfColumn = ((TableRow) usedTable.getChildAt(indexOfRow)).indexOfChild(textEdited);
		}
//		Log.d("index", "indexOfColumn  == " + indexOfColumn);
		int largestWidth = 0;
		//traverse over all columns to get biggest width
		//first columns of normal table
		for (int i = 0; i < table.getChildCount(); i++) {
			View child = table.getChildAt(i);
			TableRow oneRow = (TableRow) child;
			if (child instanceof TableRow) {
				View view = oneRow.getChildAt(indexOfColumn);
				if(view != null){
					int localWidth = 0;
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					localWidth = view.getMeasuredWidth();
					if(localWidth > largestWidth){
						largestWidth = localWidth;
					}
				}
			}
		}
		//than compare with header table also
		for (int i = 0; i < headerTable.getChildCount(); i++) {
			View child = headerTable.getChildAt(i);
			TableRow oneRow = (TableRow) child;
			if (child instanceof TableRow) {
				View view = oneRow.getChildAt(indexOfColumn);
				int localWidth = 0;
				if(view != null){
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					localWidth = view.getMeasuredWidth();
					if(localWidth > largestWidth){
						largestWidth = localWidth;
					}
				}
			}
		}
		/* Code that measures the height of one row
		int largestHeight = 0;
		if (row instanceof TableRow) {
			for(int i=0; i<((TableRow) row).getChildCount(); i++){
				View view = ((TableRow) row).getChildAt(i);
				int localHeight = 0;
				if(view instanceof EditText){
					view.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					localHeight = view.getMeasuredHeight();
					if(localHeight > largestHeight){
						largestHeight = localHeight;
					}
				}
			}
		}
		*/
		adaptAllColumnsToSize(indexOfColumn, largestWidth);
	}
	
	/**
	 * adapts all columns of the table with given columnIndex to the given width
	 * @param columnIndex
	 * @param width
	 */
	protected void adaptAllColumnsToSize(int columnIndex, int width){
		View singleRow = headerTable.getChildAt(0);
		if(singleRow instanceof TableRow){
			View theChildToResize = ((TableRow) singleRow).getChildAt(columnIndex);
			if(theChildToResize != null){
//				setHeaderTableStyle((EditText) theChildToResize);
				theChildToResize.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
				final TableRow.LayoutParams lparams = new TableRow.LayoutParams(width,getNeededHeight(0, ((TableRow) singleRow))); // Width , height
			    theChildToResize.setLayoutParams(lparams);
			}
		}
		for(int i=0; i<table.getChildCount(); i++){
			View oneRow = table.getChildAt(i);
			if(oneRow instanceof TableRow){
				View theChildToResize = ((TableRow) oneRow).getChildAt(columnIndex);
				if(theChildToResize != null){
					theChildToResize.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
					final TableRow.LayoutParams lparams = new TableRow.LayoutParams(width, getNeededHeight(i, ((TableRow) oneRow))); // Width , height
				    theChildToResize.setLayoutParams(lparams);
				}
				
			}
		}
	}
	
	/**
	 * changes amount of table columns to the given amountOfColumns
	 * @param amountOfColumns
	 */
	protected void setAmountOfColumns(int amountOfColumns){
		int amountToAdd = amountOfColumns - amountColumns;
		if(amountToAdd > 0){
			for(int i=0; i<amountToAdd; i++){
				addColumn();
			}
		}
		else{
			for(int i=amountToAdd; i<0; i++){
				removeColumn();
			}
		}
	}
	
	private EditText initEditText(final TableRow row, final IEditableContent jacksonEntry){
//		Log.d("initEditText", "jacksonEntry:"+jacksonEntry.hashCode());
		final EditText newElement = new EditText(getActivity());
		newElement.setGravity(Gravity.CENTER);
		newElement.addTextChangedListener(new TextWatcher(){
			public void afterTextChanged(Editable s) {
				checkResize(0, 0, newElement, row);
			}
			public void beforeTextChanged(CharSequence s, int start, int count, int after){
			}
			public void onTextChanged(CharSequence s, int start, int before, int count){
			}
		});
		if(row == headerTable.getChildAt(0)) {
			setHeaderTableStyle((EditText) newElement);
		}
		else {
			setTableStyle(newElement);
		}
		//
		// JACKSON START
		//
		if(jacksonEntry != null) {
			newElement.setText(jacksonEntry.getContent());
			newElement.addTextChangedListener(new TextWatcher() {
				private final IEditableContent content = jacksonEntry;
				public void afterTextChanged(Editable s) {
					// guard. only set new content if we are not currently inflating with data.
					if(!jacksonInflateWithData) {
						content.setContent(s.toString());
					}
					checkResize(0, 0, newElement, row);
				}
				public void beforeTextChanged(CharSequence s, int start, int count, int after){
				}
				public void onTextChanged(CharSequence s, int start, int before, int count){
				}
			});
		}
		//
		// JACKSON END
		//
		// we can do it like this with a check, or we change the default value in jackson model
		// check is needed, because we would otherwise overwrite the loaded value
		if(newElement.getText().toString().isEmpty()) {
			if(row == headerTable.getChildAt(0)) {
				newElement.setText(getResources().getString(R.string.headline)
								+ " "
								+ (((TableRow) headerTable.getChildAt(0))
										.getChildCount()+1));
			}	
			else {
				((EditText) newElement).setText(getResources().getString(R.string.blank));
			}
		}
//		((EditText) newElement).clearFocus();
//		setTableStyle(newElement);
		return newElement;
	}
	
    int styleStart = 0;
    int cursorLoc = 0;
    
    private ArrayList<String> getAllElementsToRef(FolderFragment fragmentToSearch){
    	ArrayList<String> results = new ArrayList<String>();
		Log.d("popupReferences", "subdirs: " + fragmentToSearch.dataAdapter.getAll().length);
        for(FolderElementData currentDatum  : fragmentToSearch.dataAdapter.getAll()){
        	GeneralFragment currentFragment = currentDatum.childFragment;
        	if(currentFragment instanceof FolderFragment){
    			Log.d("popupReferences", "folderfragment found, descending now");
        		ArrayList<String> toAdd = getAllElementsToRef((FolderFragment) currentFragment);
        		results.addAll(toAdd);
        	}
        	else if(currentFragment instanceof TableFragment){
    			Log.d("popupReferences", "tableview found");
        	}
        	else if(currentFragment instanceof MatrixFragment){
    			Log.d("popupReferences", "matrix found. Elements:" + (((MatrixFragment) currentFragment).itemsList).size());
        		for(MatrixItem oneItem : ((MatrixFragment) currentFragment).itemsList){
        			String oneName = oneItem.getItemName();
        			results.add(oneName);
        		}
        	}
        	else{
    			Log.d("popupReferences", "unhandled element found!!!");
        	}
        }
        return results;
    }
	
    private LinearLayout initPopup(final TableRow row, final IEditableContent jacksonEntry){
		Log.d("TABLE_FRAGMENT", "init_popup");

		final LinearLayout ll = new LinearLayout(getActivity());
		final TextView newElement = new TextView(getActivity());
		//
		// JACKSON START
		//
		//temporarily disabled, have to take a closer look to popups
//		if(jacksonEntry != null) {
//			newElement.setText(jacksonEntry.toString());
//			newElement.addTextChangedListener(new TextWatcher() {
//				final IEditableContent myJacksonEntry = jacksonEntry;
//				// callback
//				public void afterTextChanged(Editable s) {
//					// guard. only set column title if we are not currently inflating with data
//					if(!jacksonInflateWithData) {
//						myJacksonEntry.setContent(s.toString());
//					}
//				}
//				public void beforeTextChanged(CharSequence s, int start, int count, int after){
//				}
//				public void onTextChanged(CharSequence s, int start, int before, int count){
//				}
//			});
//		}
		//
		// JACKSON END
		//
		final TextView txt = (TextView) newElement;
		txt.addTextChangedListener(new TextWatcher(){
			public void afterTextChanged(Editable s) {
				checkResize(0, 0, txt, row);
			}
			public void beforeTextChanged(CharSequence s, int start, int count, int after){
			}
			public void onTextChanged(CharSequence s, int start, int before, int count){
			}
		});
        LayoutInflater inflater = (LayoutInflater) SlideoutNavigationActivity.theActiveActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        final View popupView = inflater.inflate(R.layout.table_view_popup, null);

//        final View layoutContainingHeadline = (View) popupView.findViewById(R.id.popup_content);
        final TextView popupHeadline = (TextView) popupView.findViewById(R.id.popup_headline);
        popupHeadline.setText(((SlideoutNavigationActivity) SlideoutNavigationActivity.theActiveActivity).getCurrentFragment().elementName);
        final EditText inputPopup = (EditText) popupView.findViewById(R.id.popup_editText);
        
        
        
        final ToggleButton toggleBold = (ToggleButton) popupView.findViewById(R.id.toggle_bold);
        toggleBold.setOnClickListener(new Button.OnClickListener() {
        	public void onClick(View v) {
        		int selectionStart = inputPopup.getSelectionStart();
        		styleStart = selectionStart;
        		// following code might be needed if they fix this bug: 
        		// http://code.google.com/p/android/issues/detail?id=62508
        		//but atm text marking in popupwindow doesnt work so we don't need to deal with 
        		//selectionEnd != selectionStart
        		/*
                int selectionEnd = inputPopup.getSelectionEnd();
                if (selectionStart > selectionEnd){
                    int temp = selectionEnd;
                    selectionEnd = selectionStart;
                    selectionStart = temp;
                }
                if (selectionEnd > selectionStart)
                {
                    Spannable str = inputPopup.getText();
                    StyleSpan[] ss = str.getSpans(selectionStart, selectionEnd, StyleSpan.class);

                    boolean exists = false;
                    for (int i = 0; i < ss.length; i++) {
                        if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
                            str.removeSpan(ss[i]);
                            exists = true;
                        }
                    }
                    if (!exists){
                        str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), selectionStart, selectionEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    toggleBold.setChecked(false);
                }
        		 */
        	}
        });
        final ToggleButton toggleItalic = (ToggleButton) popupView.findViewById(R.id.toggle_italic);
        toggleItalic.setOnClickListener(new Button.OnClickListener() {
        	public void onClick(View v) {
        		int selectionStart = inputPopup.getSelectionStart();
        		styleStart = selectionStart;
        	}
        });
        final ToggleButton toggleUnderlined = (ToggleButton) popupView.findViewById(R.id.toggle_underline);
        toggleUnderlined.setPaintFlags(Paint.UNDERLINE_TEXT_FLAG);
        toggleUnderlined.setOnClickListener(new Button.OnClickListener() {
        	public void onClick(View v) {
        		int selectionStart = inputPopup.getSelectionStart();
        		styleStart = selectionStart;
        	}
        });
        
        
        inputPopup.addTextChangedListener(new TextWatcher() { 
        	final IEditableContent myJacksonEntry = jacksonEntry;
        	public void afterTextChanged(Editable s) { 
        		int position = Selection.getSelectionStart(inputPopup.getText());
        		if (position < 0){
        			position = 0;
        		}
        		if (position > 0){
        			if (styleStart > position || position > (cursorLoc + 1)){
        				//user changed cursor location, reset
        				styleStart = position - 1;
        			}
        			cursorLoc = position;
//            		Log.d("textstyle", "styleStart == " + styleStart + ", position == " + position);
        			if (toggleBold.isChecked()){
                        StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);
                        for (int i = 0; i < ss.length; i++) {
                            if (ss[i].getStyle() == android.graphics.Typeface.BOLD){
                                s.removeSpan(ss[i]);
                            }
                        }
                        s.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    if (toggleItalic.isChecked()){
                        StyleSpan[] ss = s.getSpans(styleStart, position, StyleSpan.class);
                        for (int i = 0; i < ss.length; i++) {
                            if (ss[i].getStyle() == android.graphics.Typeface.ITALIC){
                                s.removeSpan(ss[i]);
                            }
                        }
                        s.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    if (toggleUnderlined.isChecked()){
                    	UnderlineSpan[] ss = s.getSpans(styleStart, position, UnderlineSpan.class);
                        for (int i = 0; i < ss.length; i++) {
                                s.removeSpan(ss[i]);
                        }
                        s.setSpan(new UnderlineSpan(), styleStart, position, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                    inputPopup.setText(s);
                    inputPopup.setSelection(position);
                    myJacksonEntry.setContent(s.toString());
        		}
        			
        	}
        	public void beforeTextChanged(CharSequence s, int start, int count, int after) { 
        		//unused
        	} 
        	public void onTextChanged(CharSequence s, int start, int before, int count) { 
        		
        	} 
        });
        
        // TEST
        if(!jacksonEntry.getContent().isEmpty()) {
        	inputPopup.setText(jacksonEntry.getContent());
        }
        // TEST END
        
        //before
//        toggleBold.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
//            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//                if (isChecked) {
//                	if(toggleItalic.isChecked()){
////                		inputPopup.setTextAppearance(getActivity(), R.style.italic_bold);
//                		inputPopup.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD_ITALIC));
//                	}
//                	else{
//                		inputPopup.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
//                	}
//                } else {
//                	if(toggleItalic.isChecked()){
////                		inputPopup.setTextAppearance(getActivity(), R.style.italic);
//                		inputPopup.setTypeface(Typeface.defaultFromStyle(Typeface.ITALIC));
//                	}
//                	else{
////                		inputPopup.setTextAppearance(getActivity(), R.style.normal_text);
//                		inputPopup.setTypeface(Typeface.defaultFromStyle(Typeface.NORMAL));
//                	}
//                }
//            }
//        });
        
        DisplayMetrics displayMetrics = getActivity().getResources().getDisplayMetrics();
//        float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
        float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
//        int popupHeight = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, getResources().getDimension(R.dimen.popup_height), getResources().getDisplayMetrics()));
//        int popupWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, getResources().getDimension(R.dimen.popup_width), getResources().getDisplayMetrics()));
//		int popupHeight = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, (float) (dpHeight*0.8), getResources().getDisplayMetrics()));
{'fraction_non_alphanumeric': 0.11078435491324623, 'fraction_numerical': 0.0024926829951406686, 'mean_word_length': 3.0500226860254083, 'pattern_counts': {'":': 0, '<': 77, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7249985', 'n_tokens_mistral': 23856, 'n_tokens_neox': 20721, 'n_words': 4313}