package sayi.topla.mobile;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import oracle.adfmf.java.beans.PropertyChangeListener;
import oracle.adfmf.java.beans.PropertyChangeSupport;

public class CellValueControl {
    private CellValue cells[][] = null;
    private int matris;
    private boolean yasla = false;
    private int currentToplam = 0;
    private transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    public CellValueControl(CellValue[][] cells) {
        this.cells = cells;
        matris = cells.length;
    }

    public void goUp(int rowIndex) {
        int b_index = 0;
        CellValue b_value;
        int dizi[] = new int[matris];
        for (int j = 0; j < matris; j++)
            dizi[j] = cells[j][rowIndex].getValue();
        for (int i = 0; i < matris; i++) {
            b_index = i;
            b_value = cells[b_index][rowIndex];
            toplamKontrolUp(rowIndex, b_index, b_value);
        }

        Map m = new HashMap();
        for (int i = 0; i < matris; i++) {
            if (cells[i][rowIndex].getValue() != 0)
                m.put(new Integer(i), cells[i][rowIndex]);
        }
        //reTainAllRowUp(m, rowIndex);
        randomSayiColumn(dizi, rowIndex);
    }

    private void toplamKontrolUp(int rowIndex, int b_index, CellValue b_value) {
        int sayac = b_index + 1;
        if (sayac == matris)
            return;
        do {
            CellValue sayac_value = cells[sayac][rowIndex];
            if (sayac_value.getValue() == 0) {
                sayac++;
                continue;
            } else if (b_value.getValue() == 0) {
                cells[b_index][rowIndex].setValue(sayac_value.getValue() + b_value.getValue());
                cells[sayac][rowIndex].setValue(0);
                b_value = cells[b_index][rowIndex];
                sayac = b_index + 1;
            } else if (b_value.getValue() == sayac_value.getValue()) {
                int toplam = sayac_value.getValue() + b_value.getValue();
                setCurrentToplam(getCurrentToplam() + toplam);
                cells[b_index][rowIndex].setValue(toplam);
                cells[sayac][rowIndex].setValue(0);
                b_index = b_index + 1;
                b_value = cells[b_index][rowIndex];
                sayac = b_index + 1;
            } else {
                b_value = cells[sayac][rowIndex];
                b_index = sayac;
                sayac++;
            }
        } while (sayac < matris);
    }

    private boolean isEmtyCell(CellValue[][] cellValues) {
        for (int i = 0; i < matris; i++) {
            for (int j = 0; j < matris; j++) {
                if (cellValues[i][j].getValue() == 0)
                    return true;
            }
        }
        return false;
    }

    private boolean isLeftOrRight(int rowIndex, CellValue[][] cells) {
        int sayac = 1;
        int b_index = 0;
        CellValue b_value = cells[rowIndex][b_index];
        do {
            CellValue sayac_value = cells[rowIndex][sayac];
            if (sayac_value.getValue() == 0) {
                sayac++;
                continue;
            } else if (b_value.getValue() == 0) {
                b_value = cells[rowIndex][b_index];
                sayac = b_index + 1;
                return true;
            } else if (b_value.getValue() == sayac_value.getValue()) {
                b_index = b_index + 1;
                b_value = cells[rowIndex][b_index];
                sayac = b_index + 1;
                return true;
            } else {
                b_value = cells[rowIndex][sayac];
                b_index = sayac;
                sayac++;
            }
        } while (sayac < matris);
        return false;
    }

    private boolean isDownOrUp(int rowIndex, CellValue[][] cells) {
        int sayac = 1;
        int b_index = 0;
        CellValue b_value = cells[b_index][rowIndex];
        do {
            CellValue sayac_value = cells[sayac][rowIndex];
            if (sayac_value.getValue() == 0) {
                sayac++;
                continue;
            } else if (b_value.getValue() == 0) {
                b_value = cells[b_index][rowIndex];
                sayac = b_index + 1;
                return true;
            } else if (b_value.getValue() == sayac_value.getValue()) {
                b_index = b_index + 1;
                b_value = cells[b_index][rowIndex];
                sayac = b_index + 1;
                return true;
            } else {
                b_value = cells[sayac][rowIndex];
                b_index = sayac;
                sayac++;
            }
        } while (sayac < matris);
        return false;
    }

    public boolean isGameOver(CellValue[][] cellValues) {
        boolean rightleft = false; //dešižiklik yok
        boolean downUp = false;// dešižiklik yok
        if (!isEmtyCell(cellValues)) {
            for (int i = 0; i < cellValues.length; i++) {
                if (isLeftOrRight(i, cellValues)) {
                    rightleft = true; //dešižiklik var
                    break;
                }
            }
            if (!rightleft) {
                for (int i = 0; i < cellValues.length; i++) {
                    if (isDownOrUp(i, cellValues)) {
                        downUp = true;
                        break;
                    }
                }
            }
            return downUp || rightleft;
        }

        return true;
    }

    private void randomSayiRow(int[] dizi, int rowIndex) {
        for (int i = 0; i < matris; i++) {
            if (cells[rowIndex][i].getValue() != dizi[i]) {
                setYasla(true);
                break;
            }
        }
    }

    private void randomSayiColumn(int[] dizi, int rowIndex) {
        for (int i = 0; i < matris; i++) {
            if (cells[i][rowIndex].getValue() != dizi[i]) {
                setYasla(true);
                break;
            }
        }
    }

    public void goDown(int rowIndex) {
        int b_index = 0;
        CellValue b_value;
        int cellValue[] = new int[matris];
        for (int j = 0; j < matris; j++) {
            cellValue[j] = cells[j][rowIndex].getValue();
        }
        for (int i = matris; i > 0; i--) {
            b_index = i - 1;
            b_value = cells[b_index][rowIndex];
            toplamKontrolDown(rowIndex, b_index, b_value);
        }

        Map m = new HashMap();
        for (int i = 0; i < matris; i++) {
            if (cells[i][rowIndex].getValue() != 0)
                m.put(new Integer(i), cells[i][rowIndex]);
        }
        //reTainAllRowDown(m, rowIndex);
        randomSayiColumn(cellValue, rowIndex);
    }

    private void toplamKontrolDown(int rowIndex, int b_index, CellValue b_value) {
        int sayac = b_index - 1;
        if (sayac == -1)
            return;
        do {
            CellValue sayac_value = cells[sayac][rowIndex];
            if (sayac_value.getValue() == 0) {
                sayac--;
                continue;
            } else if (b_value.getValue() == 0) {
                cells[b_index][rowIndex].setValue(sayac_value.getValue() + b_value.getValue());
                cells[sayac][rowIndex].setValue(0);
                b_value = cells[b_index][rowIndex];
                sayac = b_index - 1;
            } else if (b_value.getValue() == sayac_value.getValue()) {
                int toplam = sayac_value.getValue() + b_value.getValue();
                setCurrentToplam(getCurrentToplam() + toplam);
                cells[b_index][rowIndex].setValue(toplam);
                cells[sayac][rowIndex].setValue(0);
                b_index = b_index - 1;
                b_value = cells[b_index][rowIndex];
                sayac = b_index - 1;
            } else {
                b_value = cells[sayac][rowIndex];
                b_index = sayac;
                sayac--;
            }
        } while (sayac >= 0);
    }


    public void goRight(int rowIndex) {
        int b_index = 0;
        CellValue b_value;
        int dizi[] = new int[matris];
        for (int j = 0; j < matris; j++)
            dizi[j] = cells[rowIndex][j].getValue();
        for (int i = matris; i > 0; i--) {
            b_index = i - 1;
            b_value = cells[rowIndex][b_index];
            toplamKontrolR(rowIndex, b_index, b_value);
        }

        Map m = new HashMap();
        for (int i = 0; i < matris; i++) {
            if (cells[rowIndex][i].getValue() != 0)
                m.put(new Integer(i), cells[rowIndex][i]);
        }
        //reTainAllRowRight(m, rowIndex);
        randomSayiRow(dizi, rowIndex);
    }

    private void toplamKontrolR(int rowIndex, int b_index, CellValue b_value) {
        int sayac = b_index - 1;
        if (sayac == -1)
            return;
        do {
            CellValue sayac_value = cells[rowIndex][sayac];
            if (sayac_value.getValue() == 0) {
                sayac--;
                continue;
            } else if (b_value.getValue() == 0) {
                cells[rowIndex][b_index].setValue(sayac_value.getValue() + b_value.getValue());
                cells[rowIndex][sayac].setValue(0);
                b_value = cells[rowIndex][b_index];
                sayac = b_index - 1;
            } else if (b_value.getValue() == sayac_value.getValue()) {
                int toplam = sayac_value.getValue() + b_value.getValue();
                setCurrentToplam(getCurrentToplam() + toplam);
                cells[rowIndex][b_index].setValue(toplam);
                cells[rowIndex][sayac].setValue(0);
                b_index = b_index - 1;
                b_value = cells[rowIndex][b_index];
                sayac = b_index - 1;
            } else {
                b_value = cells[rowIndex][sayac];
                b_index = sayac;
                sayac--;
            }
        } while (sayac >= 0);
    }

    public void goLeft(int rowIndex) {
        int b_index = 0;
        CellValue b_value;
        int dizi[] = new int[matris];
        for (int j = 0; j < matris; j++)
            dizi[j] = cells[rowIndex][j].getValue();
        for (int i = 0; i < matris; i++) {
            b_index = i;
            b_value = cells[rowIndex][b_index];
            toplamKontrolL(rowIndex, b_index, b_value);
        }

        Map m = new HashMap();
        for (int i = 0; i < matris; i++) {
            if (cells[rowIndex][i].getValue() != 0)
                m.put(new Integer(i), cells[rowIndex][i]);
        }
        //reTainAllRowLeft(m, rowIndex);
        randomSayiRow(dizi, rowIndex);
    }

    private void toplamKontrolL(int rowIndex, int b_index, CellValue b_value) {
        int sayac = b_index + 1;
        if (sayac == matris)
            return;
        do {
            CellValue sayac_value = cells[rowIndex][sayac];
            if (sayac_value.getValue() == 0) {
                sayac++;
                continue;
            } else if (b_value.getValue() == 0) {
                cells[rowIndex][b_index].setValue(sayac_value.getValue() + b_value.getValue());
                cells[rowIndex][sayac].setValue(0);
                b_value = cells[rowIndex][b_index];
                sayac = b_index + 1;
            } else if (b_value.getValue() == sayac_value.getValue()) {
                int toplam = sayac_value.getValue() + b_value.getValue();
                setCurrentToplam(getCurrentToplam() + toplam);
                cells[rowIndex][b_index].setValue(toplam);
                cells[rowIndex][sayac].setValue(0);
                b_index = b_index + 1;
                b_value = cells[rowIndex][b_index];
                sayac = b_index + 1;
            } else {
                b_value = cells[rowIndex][sayac];
                b_index = sayac;
                sayac++;
            }
        } while (sayac < matris);
    }

    public void setYasla(boolean yasla) {
        this.yasla = yasla;
    }

    public boolean isYasla() {
        return yasla;
    }

    public void setCells(CellValue[][] cells) {
        this.cells = cells;
    }

    public CellValue[][] getCells() {
        return cells;
    }

    public void setCurrentToplam(int currentToplam) {
        int oldCurrentToplam = this.currentToplam;
        this.currentToplam = currentToplam;
        propertyChangeSupport.firePropertyChange("currentToplam", oldCurrentToplam, currentToplam);
    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.removePropertyChangeListener(l);
    }

    public int getCurrentToplam() {
        return currentToplam;
    }
}

