package jp.gr.java_conf.shiseissi.commonlib;

import android.app.Activity;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewStub;
import android.view.Window;

/**
 *
 * @author shisei
 */
public abstract class ViewUtil {

    /**
     * 型推論を使用した {@link View#findViewById(int)} の実行
     * @param v
     * @param id
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends View> T findViewById(View v, int id) {
        return (T) v.findViewById(id);
    }

    /**
     * 型推論を使用した {@link Activity#findViewById(int)} の実行
     * @param a
     * @param id
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends View> T findViewById(Activity a, int id) {
        return (T) a.findViewById(id);
    }

    /**
     * 型推論を使用した {@link Window#findViewById(int)} の実行
     * @param w
     * @param id
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends View> T findViewById(Window w, int id) {
        return (T) w.findViewById(id);
    }

    /**
     * 型推論を使用した {@link FragmentManager#findFragmentById(int)} の実行
     * @param f
     * @param id
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends Fragment> T findFragmentById(FragmentManager f, int id) {
        return (T) f.findFragmentById(id);
    }

    /**
     * 型推論を使用した {@link FragmentManager#findFragmentByTag(String)} の実行
     * @param f
     * @param tag
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends Fragment> T findFragmentByTag(FragmentManager f, String tag) {
        return (T) f.findFragmentByTag(tag);
    }

    /**
     * 型推論を使用した {@link LayoutInflater#inflate(int, ViewGroup, boolean)} の実行
     * @param <T>
     * @param inflater
     * @param resource
     * @param root
     * @param attachToRoot
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends View> T inflate(LayoutInflater inflater, int resource,
            ViewGroup root, boolean attachToRoot) {
        return (T) inflater.inflate(resource, root, attachToRoot);
    }

    /**
     * dst と同じIDを持つViewを srcRoot から探し、
     * その ViewGroup.LayoutParams を dst へとコピーする
     * @param dst
     * @param srcRoot
     */
    public static void copyLayoutParamsById(View dst, ViewGroup srcRoot) {
        dst.setLayoutParams(srcRoot.findViewById(
                dst.getId()).getLayoutParams());
    }

    /**
     * before を親のViewGroupから切り離し、 after と入れ替える
     * @param before
     * @param after
     */
    public static void replaceView(View before, View after) {
        ViewGroup parent = (ViewGroup) before.getParent();
        int index = parent.indexOfChild(before);
        assert index >= 0;
        parent.removeViewAt(index);
        parent.addView(after, index);
    }

    /**
     * view を親のViewGroupから切り離す
     * @param view
     * @return view
     */
    public static View removeViewFromParent(View view) {
        ViewParent parent = view.getParent();
        if (parent instanceof ViewGroup) {
            ((ViewGroup) parent).removeView(view);
        }
        return view;
    }

    /**
     * 子ViewのVisibilityを変更する
     * @param viewGroup
     * @param visibility
     */
    public static void setChildVisibility(ViewGroup viewGroup, int visibility) {
        int count = viewGroup.getChildCount();
        for (int i = 0; i < count; ++i) {
            View view = viewGroup.getChildAt(i);
            if (view != null) {
                view.setVisibility(visibility);
            }
        }
    }

    /**
     * 型推論を使用した {@link ViewStub#inflate} の実行
     * @param stub
     * @return
     */
    @SuppressWarnings("unchecked")
    public static <T extends View> T inflate(ViewStub stub) {
        return (T) stub.inflate();
    }
}
