package com.hikapro.backpack.model;

import android.os.Message;
import android.widget.Toast;

import com.hikapro.backpack.App;
import com.hikapro.backpack.model.dao.Command;
import com.hikapro.backpack.model.dao.DAO;
import com.hikapro.backpack.model.dao.Event;
import com.hikapro.backpack.model.entities.Category;
import com.hikapro.backpack.model.entities.Item;
import com.hikapro.backpack.presenter.Presenter;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;

/**
 * Created by tariel on 18/05/16.
 */
public class AddModel implements Model.Add {

    private Presenter.Add                   presenter;
    private DAO                             dao;
    private List<Item>                      filteredItems;
    private List<Category>                  categoriesCache;

    public AddModel() {
        this.filteredItems      = new ArrayList<>(256);
        this.categoriesCache    = new ArrayList<>(20);
        this.dao = DAO.getInstance();
    }

    @Override
    public void onEvent(Message event) {

        switch (event.what) {

            case Event.ITEM_LIKE_LOAD_ERROR :
                if (!filteredItems.isEmpty()) {
                    filteredItems.clear();
                }
                notifyDataSetChanged();
                break;

            case Event.ITEM_CATEGORY_LOAD_ERROR :
                break;

            case Event.ITEM_INSERT_ERROR :
                Toast.makeText(App.getAppContext(), "Item not inserted!", Toast.LENGTH_SHORT).show();
                break;

            case Event.ITEM_LIKE_LOAD_COMPLETED :
                filteredItems = (List<Item>) event.obj;
                notifyDataSetChanged();
                break;

            case Event.ITEM_CATEGORY_LOAD_COMPLETED :
                Hashtable<Integer, Category> res = (Hashtable<Integer, Category>)event.obj;
                categoriesCache = new ArrayList<>(res.values()); // TODO check utilization
                break;

            case Event.ITEM_INSERTED :
                Toast.makeText(App.getAppContext(), "New item inserted", Toast.LENGTH_SHORT).show();
                break;
        }
    }

    @Override
    public void onDestroy(boolean isConfigurationChanging) {
        if ( !isConfigurationChanging ) {
            presenter = null;
        }
        dao.unregisterObserver(this);
    }

    @Override
    public void executeQuery() {
        Message command;
        dao.registerObserver(this);
        if (categoriesCache.isEmpty()) {
            command = Message.obtain();
            command.what = Command.ITEM_GET_CATEGORIES;
            dao.executeCommand(command);
        }
    }

    @Override
    public void add(Item item, int setId) {
        Message command;
        command = Message.obtain();
        command.what = Command.ITEM_INSERT;
        command.obj = item;
        command.arg1 = setId;
        dao.executeCommand(command);
    }

    @Override
    public void filter(String query, int checkThisSet) {

        if (!query.isEmpty()) {
            Message command = Message.obtain();
            command.what = Command.ITEM_GET_LIKE;
            command.arg1 = checkThisSet;
            query = query.toLowerCase();
            command.obj = query;
            dao.executeCommand(command);
        }
    }

    @Override
    public void notifyDataSetChanged() {
        boolean res = !filteredItems.isEmpty();
        presenter.notifyDataSetChanged(res);
    }

    @Override
    public int getItemsCount() {
        return filteredItems.size();
    }

    @Override
    public Item getItemByPosition(int position) {
        return filteredItems.get(position);
    }

    @Override
    public int getCategoriesCount() {
        return categoriesCache.size();
    }

    @Override
    public Category getCategoryByPosition(int position) {
        return categoriesCache.get(position);
    }

    @Override
    public Category getCategoryById(int id) {
        for (Category category : categoriesCache) {
            if (category.getId() == id)
                return category;
        }
        return null;
    }

    @Override
    public void setPresenter(Presenter.Add presenter) {
        this.presenter  = presenter;
    }

    @Override
    public Presenter.Add getPresenter() {
        return presenter;
    }
}
