package com.baidu.rtc.sample.splitscreen;

import static android.os.Looper.getMainLooper;

import android.app.Fragment;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.baidu.rtc.BaiduRtcRoom;
import com.baidu.rtc.RTCVideoView;
import com.baidu.rtc.sample.R;
import com.baidu.rtc.sample.data.RtcClientData;
import com.baidu.rtc.sample.util.ScreenUtil;
import com.baidu.rtc.sample.util.UIUtils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * viewPager
 * childView  gridView
 */
public class DefaultFragment extends Fragment implements IRemoteVideoListener {
    private static final String TAG = "DefaultFragment";

    /** 16:9， 本地预览全屏【大屏】 远端画面【小屏】*/
    private static final int DISPLAY_RECTANGLE = 1;

    /** 方块显示， 本地预览右上角【小屏】 远端画面【大屏】*/
    private static final int DISPLAY_SQUARE_1 = 2;
    private int mDisplayMode = DISPLAY_SQUARE_1;

    /**
     * 最多显示4个
     */
    private static final int MAX_USER_COUNT = 4;
    private final float mDisplayRatio = 16.0f / 9.f;

    private Context mContext;
    public BaiduRtcRoom mVideoRoom;
    private RtcClientData mClientData;
    private Handler mHandler;
    private FrameLayout mContentLayout;
    private FrameLayout mLocalLayout;
    private final List<Long> mRemoteUsers = new ArrayList<>();
    private final List<View> mRemoteViews = new ArrayList<>();
    private final Queue<Long> mPendingRemoteUsers = new LinkedList<>();

    private ToolsView mToolsView = new ToolsView();
    public void setVideoRoom(BaiduRtcRoom videoRoom) {
        mVideoRoom = videoRoom;
    }

    public void setClientData(RtcClientData clientData) {
        mClientData = clientData;
    }

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

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

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        mContext = context;
        mHandler = new Handler(getMainLooper());
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        if (mContext == null) {
            /** 暂时使用view context */
            Log.e(TAG, "onViewCreated, but not callback onAttach!");
            mContext = view.getContext();
        }
        // 表格输出
        mContentLayout = view.findViewById(R.id.content_layout);

        setLocalView();
        addToolsView();
    }

    public RTCVideoView getLocalView() {
        if (mLocalLayout == null) {
            return null;
        }
        return (RTCVideoView) mLocalLayout.getChildAt(0);
    }

    @Override
    public void onRemoteUserJoin(long userId, String name) {
        if (mClientData.mAutoSubscribe) { // 自动订阅的时候才走
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    Log.i(TAG, "RTC_ROOM_EVENT_REMOTE_COMING = " + userId);
                    if (mVideoRoom == null) {
                        return;
                    }
                    int index = mRemoteUsers.indexOf(userId);
                    if (index < 0) {
                        onComing(userId);
                    }
                }
            });
        }
    }

    @Override
    public void onRemoteUserLeave(long userId, String name) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                Log.i(TAG, "RTC_ROOM_EVENT_REMOTE_LEAVING = " + userId);
                if (mVideoRoom == null) {
                    return;
                }
                onLeaving(userId);
            }
        });
    }

    public void onLeaving(Long userId) {
        if (mRemoteViews.size() == 0) {
            return;
        }
        notifyViewRemoved(userId);
    }

    private void notifyViewRemoved(long data) {
        int index = mRemoteUsers.indexOf(data);
        if (index < 0) {
            Log.i(TAG, "notifyViewRemoved index < 0");
            return;
        }

        View remoteView = mRemoteViews.get(index);
        mContentLayout.removeView(remoteView);
        mRemoteViews.remove(remoteView);
        mRemoteUsers.remove(data);
        adaptContentLayout();
        if (mPendingRemoteUsers.size() > 0) {
            onComing(mPendingRemoteUsers.poll());
        } else {
            if ((mRemoteViews.size() < 4 && mRemoteViews.size() > 1) || mRemoteViews.size() < 2) {
                processRenderViewChanged(0, mLocalLayout, true);
            }
            for (int i = 0; i < mRemoteViews.size(); i++) {
                processRenderViewChanged(i + 1, mRemoteViews.get(i), false);
            }
        }
    }

    private void addToolsView() {
        if (!mClientData.mIsWatch) {
            return;
        }
        View view = mToolsView.onCreate(mContext, new ToolsView.Callback() {
            @Override
            public void onViewClick(int type) {
                if (mRemoteViews.size() == 1) {
                    View view = mRemoteViews.get(0);
                    ToolsView.changeLayoutParams(view, type);
                }
            }
        });
        mContentLayout.addView(view,
                new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
    }

    private void setLocalView() {
        RTCVideoView rtcVideoView = new RTCVideoView(mContext);
        // 设置视频显示类型，SCALE_ASPECT_FILL 填充，
        if (!mClientData.mIsWatch) {
            rtcVideoView.setScalingType(RTCVideoView.ScalingType.SCALE_ASPECT_FILL);
        }
        mVideoRoom.setLocalDisplay(rtcVideoView);
        FrameLayout layout = new FrameLayout(mContext);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        layout.setBackgroundResource(R.drawable.bg_video_placeholder);
        int padding = UIUtils.dip2px(mContext, 1);
        layout.setPadding(padding, padding, padding, padding);
        params.gravity = Gravity.CENTER;
        layout.addView(rtcVideoView, params);

        FrameLayout.LayoutParams paramsTextView = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        paramsTextView.gravity = Gravity.BOTTOM | Gravity.RIGHT;
        int margin = UIUtils.dip2px(mContext, 10);
        paramsTextView.leftMargin = margin;
        paramsTextView.topMargin = margin;
        paramsTextView.rightMargin = margin;
        paramsTextView.bottomMargin = margin;
        TextView textView = new TextView(mContext);
        textView.setTextColor(Color.WHITE);
        textView.setTextSize(10f);
        textView.setText(String.format("uid：%s", mClientData.mUserId));
        layout.addView(textView, paramsTextView);

        processRenderViewChanged(0, layout, true);
        mContentLayout.addView(layout, 0);
        mLocalLayout = layout;
    }

    public void onComing(Long userId) {
        onComing(userId, mClientData.mHasRemoteVideo);
    }

    public void onComing(Long userId, boolean visible) {
        if (mRemoteViews.size() >= MAX_USER_COUNT - 1) {
            mPendingRemoteUsers.offer(userId);
            return;
        }
        // 检查是否已经coming过，设置visible
        int index = mRemoteUsers.indexOf(userId);
        if (index >= 0 && visible) {
            Log.i(TAG, "has coming.");
            View view = mRemoteViews.get(index);
            if (view instanceof ViewGroup) {
                View inner = ((ViewGroup) view).getChildAt(0);
                if (inner instanceof RTCVideoView) {
                    inner.setVisibility(View.VISIBLE);
                }
            }
            return;
        }

        RTCVideoView rtcVideoView = new RTCVideoView(mContext);
        if (!mClientData.mIsWatch) {
            rtcVideoView.setScalingType(RTCVideoView.ScalingType.SCALE_ASPECT_FILL);
        }
        /** 打开超分 */
        if (mClientData.mIsWatch) {
           rtcVideoView.setSrEnable(true, Float.parseFloat(mClientData.mVideoFps));
        }
        mVideoRoom.setRemoteDisplay(rtcVideoView, userId);
        FrameLayout layout = new FrameLayout(mContext);
        layout.setTag(userId);
        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT);
        layout.setBackgroundResource(R.drawable.bg_video_placeholder);
        int padding = UIUtils.dip2px(mContext, 1);
        layout.setPadding(padding, padding, padding, padding);
        params.gravity = Gravity.TOP | Gravity.RIGHT;
        layout.addView(rtcVideoView, params);

        FrameLayout.LayoutParams paramsTextView = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT);
        paramsTextView.gravity = Gravity.BOTTOM | Gravity.END;
        int margin = UIUtils.dip2px(mContext, 10);
        paramsTextView.leftMargin = margin;
        paramsTextView.topMargin = margin;
        paramsTextView.rightMargin = margin;
        paramsTextView.bottomMargin = margin;
        TextView textView = new TextView(mContext);
        textView.setTextColor(Color.WHITE);
        textView.setTextSize(11f);
        textView.setText(String.valueOf("uid：" + userId));
        layout.addView(textView, paramsTextView);

        rtcVideoView.setVisibility(visible ? View.VISIBLE : View.GONE);
        notifyViewAdded(userId, layout);
    }

    private void notifyViewAdded(long data, ViewGroup layout) {
        mRemoteUsers.add(data);
        mRemoteViews.add(layout);
        if ((mRemoteViews.size() > 1 && mRemoteViews.size() < 4) || mRemoteViews.size() > 3) {
            processRenderViewChanged(0, mLocalLayout, true);
        }
        for (int i = 0; i < mRemoteViews.size(); i++) {
            processRenderViewChanged(i + 1, mRemoteViews.get(i), false);
        }
        mContentLayout.addView(layout);
        adaptContentLayout();
    }

    private void adaptContentLayout() {
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mContentLayout.getLayoutParams();
        if (params == null) {
            params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);
        }
        params.height = ViewGroup.LayoutParams.MATCH_PARENT;
        mContentLayout.setLayoutParams(params);
    }

    private void processRenderWatch(View view, boolean isLocalView) {
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
        if (params == null) {
            params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        float displayRatio = mDisplayRatio;

        int itemWidth = (int) ScreenUtil.getScreenWidth();
        int itemHeight = (int) (itemWidth * displayRatio);

        if (mRemoteViews.size() == 0) {
            itemWidth = (int) ScreenUtil.getScreenWidth();
            itemHeight = (int) (itemWidth * displayRatio);
            params.gravity = Gravity.CENTER_HORIZONTAL;
            params.topMargin = 0;
            params.leftMargin = 10;
            view.setBackgroundResource(android.R.color.transparent);
        } else if (mRemoteViews.size() < 2) {
            itemWidth = (int) (ScreenUtil.getScreenWidth() * (!isLocalView ? 0.4f : 1.0f));
            itemHeight = (int) (itemWidth * displayRatio);
            params.gravity = !isLocalView ? Gravity.RIGHT : Gravity.CENTER_HORIZONTAL;
            params.topMargin = 0;
            params.leftMargin = 10;

            view.setBackgroundResource(android.R.color.transparent);
            if (!isLocalView) {
                itemWidth = (int) (ScreenUtil.getScreenWidth());
                itemHeight = (int) (itemWidth * mClientData.videoHeight / mClientData.videoWidth);
                Log.e(TAG, "processRenderViewChanged watch w:" + itemWidth + ", h:" + itemHeight);
            }
        }
        params.width = itemWidth;
        params.height = itemHeight;
        view.setLayoutParams(params);
    }

    private void processRenderWatch2(View view, boolean isLocalView) {
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
        if (params == null) {
            params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        float displayRatio = mDisplayRatio;

        int itemWidth = (int) ScreenUtil.getScreenWidth();
        int itemHeight = (int) (itemWidth * displayRatio);

        if (mRemoteViews.size() == 0) {
            /** 本地预览 */
            itemWidth = 400;
            itemHeight = 400;
            params.gravity = Gravity.RIGHT;
            params.topMargin = 10;
            params.rightMargin = 10;
            view.setBackgroundResource(android.R.color.transparent);
        } else if (mRemoteViews.size() < 2) {
            if (isLocalView) {
                return;
            }

            itemWidth = 700;
            itemHeight = 700;
            params.gravity =  Gravity.CENTER_HORIZONTAL;
            params.topMargin = 430;
            view.setBackgroundResource(android.R.color.transparent);
        }
        params.width = itemWidth;
        params.height = itemHeight;
        view.setLayoutParams(params);
    }

    private void processRenderViewChanged(int index, View view, boolean isLocalView) {
        if (mClientData.mIsWatch) {
            if (mDisplayMode == DISPLAY_RECTANGLE) {
                processRenderWatch(view, isLocalView);
            } else if (mDisplayMode == DISPLAY_SQUARE_1) {
                /** 方块显示， 本地预览右上角【小屏】 远端画面【大屏】*/
                processRenderWatch2(view, isLocalView);
            }
            return;
        }
        FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams();
        if (params == null) {
            params = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        float displayRatio = mDisplayRatio;
        int padding = UIUtils.dip2px(mContext, 10);
        int heightLeft = ScreenUtil.getScreenHeight() - UIUtils.dip2px(mContext, 90);
        int widthLeft = ScreenUtil.getScreenWidth();
        int itemHeight;
        int itemWidth;
        if (mRemoteViews.size() == 0) {
            itemWidth = (int) ScreenUtil.getScreenWidth();
            itemHeight = (int) (itemWidth * displayRatio);
            params.gravity = Gravity.CENTER_HORIZONTAL;
            params.topMargin = 0;
            params.leftMargin = 10;

            view.setBackgroundResource(android.R.color.transparent);
        } else if (mRemoteViews.size() < 2) {
            itemWidth = (int) (ScreenUtil.getScreenWidth() * (!isLocalView ? 0.4f : 1.0f));
            itemHeight = (int) (itemWidth * displayRatio);
            params.gravity = !isLocalView ? Gravity.RIGHT : Gravity.CENTER_HORIZONTAL;
            params.topMargin = 0;
            params.leftMargin = 10;

            view.setBackgroundResource(android.R.color.transparent);
        } else {
            // 四分布局
            int row = 2;
            int column = 2;

            int maxItemHeight = heightLeft / row;
            int maxItemWidth = widthLeft / column;
            itemHeight = maxItemHeight;
            itemWidth = (int) (itemHeight / displayRatio);
            while (itemWidth > maxItemWidth) {
                itemWidth -= padding;
                itemHeight = (int) (itemWidth * displayRatio);
            }
            int paddingTop = 0;
            int paddingLeft = 10;
            params.gravity = Gravity.NO_GRAVITY;
            // 依据index存放位置
            // 0 1
            int columnCoefficient = index % column;
            int rowCoefficient = index / row;
            params.leftMargin = paddingLeft + itemWidth * columnCoefficient;
            params.topMargin = paddingTop + itemHeight * rowCoefficient;
            view.setBackgroundResource(R.drawable.bg_video_placeholder);
        }
        params.width = itemWidth;
        params.height = itemHeight;
        view.setLayoutParams(params);
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (mVideoRoom != null) {
            mVideoRoom = null;
        }
        mRemoteUsers.clear();
        mRemoteViews.clear();
        mPendingRemoteUsers.clear();
    }
}
