/*
 * Copyright (c) 2015  Zvooq LTD.
 * Authors: Renat Sarymsakov, Dmitriy Mozgin, Denis Volyntsev.
 *
 * This file is part of Visum.
 *
 * Visum is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Visum is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Visum.  If not, see <http://www.gnu.org/licenses/>.
 */

package io.reist.visum.view;

import android.os.Bundle;
import android.support.annotation.LayoutRes;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import io.reist.visum.ComponentCache;
import io.reist.visum.ComponentCacheProvider;
import io.reist.visum.VisumClient;
import io.reist.visum.presenter.VisumPresenter;

/**
 * Base class for Fragments providing visum mvp inteface
 *
 * @param <P> - subclass of VisumPresenter
 */
public abstract class VisumDialogFragment<P extends VisumPresenter> extends DialogFragment implements VisumView<P>, VisumClient {

    private static final String ARG_STATE_COMPONENT_ID = "ARG_STATE_COMPONENT_ID";

    private Long componentId;
    private boolean stateSaved;
    private int layoutResId;

    public VisumDialogFragment(@LayoutRes int layoutResId) {
        this.layoutResId = layoutResId;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        componentId = savedInstanceState == null ? null : savedInstanceState.getLong(ARG_STATE_COMPONENT_ID);
        stateSaved = false;

        inject(getComponent());
    }

    /// --- ///

    public final String getName() {
        return getClass().getName();
    }

    //region VisumClient implementation

    @Override
    public final Long getComponentId() {
        return componentId;
    }

    /**
     * Sets component id for current view
     *
     * @param componentId - unique id generated by ComponentCache
     */
    @Override
    public final void setComponentId(Long componentId) {
        this.componentId = componentId;
    }

    @Override
    public final Object getComponent() {
        if (getComponentCache() != null) {
            return getComponentCache().getComponentFor(this);
        } else {
            return null;
        }
    }

    @Override
    public ComponentCache getComponentCache() {
        ComponentCacheProvider application = (ComponentCacheProvider) getActivity().getApplication();
        return application.getComponentCache();
    }

    //endregion

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(layoutResId, container, false);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        attachPresenter();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putLong(ARG_STATE_COMPONENT_ID, componentId);
        stateSaved = true;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (!stateSaved) {
            onInvalidateComponent();
        }
        detachPresenter();
    }

    protected void onInvalidateComponent() {
        getComponentCache().invalidateComponentFor(this);
    }

    //region VisumView implementation

    /**
     * <p>
     * attachPresenter is called {@link VisumDialogFragment#onViewCreated(View, Bundle)} on Fragment initialization.
     * If you need to execute some code when View is initialized, but before presenter is attached
     * just use following snippet:
     * </p>
     * <pre>
     * {@code
     * @literal @Override
     * public void onViewCreated(View view, Bundle savedInstanceState) {
     *      //your code here
     *      super.onViewCreated(view, savedInstanceState);
     * }
     * </pre>
     * <p>
     * attachPresenter is also called once fragment is shown after it has been hidden.
     * Symmetrically {@link VisumDialogFragment#detachPresenter()} is called on fragment hidden and on Destroy View
     * </p>
     */
    @SuppressWarnings("unchecked") //todo setView should be checked call
    @Override
    public void attachPresenter() {
        final P presenter = getPresenter();
        if (presenter != null) {
            presenter.setView(this);
        }
    }

    @SuppressWarnings("unchecked") //todo setView should be type safe call
    @Override
    public void detachPresenter() {
        final P presenter = getPresenter();
        if (presenter != null)
            presenter.setView(null);
    }

    //endregion

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (hidden) {
            detachPresenter();
        } else {
            attachPresenter();
        }
    }

}

add VisumDialogFragment