package org.ntlab.acanthus_client.views.paint;

import android.util.Log;
import android.view.MotionEvent;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import org.ntlab.acanthus_client.Acanthus;
import org.ntlab.acanthus_client.entities.Stroke;
import org.ntlab.acanthus_client.views.paint.models.PageConnectionModel;
import org.ntlab.acanthus_client.views.paint.models.PageOperationModel;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


//-----------------------------------------------------------------
// 描画処理の仲介
public class PaintViewModel extends ViewModel implements Runnable {
    private PaintModelContainer paintModelContainer;

    private MutableLiveData<Integer> mCurPageNo = new MutableLiveData<>(1);
    private MutableLiveData<Integer> mCurPageId = new MutableLiveData<>(0);
    private MutableLiveData<Integer> mPageSize = new MutableLiveData<>(0);
    private MutableLiveData mStrokeNo = new MutableLiveData(0);
    private MutableLiveData<Collection<Stroke>> mStrokes = new MutableLiveData<>();
    private int strokeNo = 0;

    private ScheduledThreadPoolExecutor thread = new ScheduledThreadPoolExecutor(1);
    private int cnt = 0;
    private float fsx = 0;
    private float fsy = 0;

    //-----------------------------------------------------------------
    // getter
    public MutableLiveData<Collection<Stroke>> getStroke() {
        return this.mStrokes;
    }

    public int getStrokeNo() {
        return this.strokeNo;
    }

    public LiveData<Integer> getPageNo() {
        return this.mCurPageNo;
    }

    public PaintModelContainer getPaintModelContainer() {
        return paintModelContainer;
    }

    //-----------------------------------------------------------------
    //-----------------------------------------------------------------
    //  init
    public void init(Acanthus acanthus) {
        paintModelContainer = new PaintModelContainer(acanthus);
        paintModelContainer.getPaintConnectionModel().init(acanthus);
        paintModelContainer.getInvitesConnectionModel().init(acanthus);

        mStrokes.setValue(new ArrayList<>());
        mStrokes.getValue().add(new Stroke());

        // ページの情報初期化
        paintModelContainer.getPageConnectionModel().getPage(mCurPageId);
        paintModelContainer.getPageConnectionModel().getPageSize(mPageSize);

        thread.scheduleWithFixedDelay(this, 1000L, 100L, TimeUnit.MILLISECONDS);
    }

    //-----------------------------------------------------------------
    // strokeNoの発行
    public void setmStrokeNo() {
        Random random = new Random();
        strokeNo = random.nextInt(1000000000);
        Log.d("TAG", "setmStrokeNo: " + mStrokeNo);
    }

    //-----------------------------------------------------------------
    // 描画APIの通信リクエスト
    public void addLocalStrokeRequest(float x, float y) {
        paintModelContainer.getPaintConnectionModel().addLocalStroke(strokeNo);
        fsx = x;
        fsy = y;
        cnt = 1;
    }

    //-----------------------------------------------------------------
    //
    public void addPositionRequest(float x, float y) {
//        Log.d("mStrokeNo", mStrokeNo.getValue().toString());
        paintModelContainer.getPaintConnectionModel().addPosition(cnt, x, y, strokeNo);
        cnt++;
    }

    //-----------------------------------------------------------------
    //
    public void addPositionRequestFirst() {
        paintModelContainer.getPaintConnectionModel().addPosition(0, fsx, fsy, strokeNo);
        paintModelContainer.getPaintConnectionModel().addPosition(cnt, -1, -1, strokeNo);
    }

    //-----------------------------------------------------------------
    // 招待APIの通信リクエスト
    public void inviteNewUserRequest(Integer invitedUid) {
        paintModelContainer.getInvitesConnectionModel().inviteNewEditor(invitedUid);
    }

    //-----------------------------------------------------------------
    // 描画情報の全クリア通信リクエスト
    public void deleteStrokesRequest() {
        paintModelContainer.getPaintConnectionModel().deleteStrokes();
    }

    //-----------------------------------------------------------------
    // 操作するページを切り替える
    public void switchToEditPageRequest(MotionEvent event) {
        PageOperationModel pageOperationModel = paintModelContainer.getPageOperationModel();
        PageConnectionModel pageConnectionModel = paintModelContainer.getPageConnectionModel();

        pageOperationModel.changeEditPageNo(event, mCurPageNo, mPageSize.getValue());
        //ページを操作したのでIdとページ番号を更新
        pageConnectionModel.getPage(mCurPageId);

    }

    //-----------------------------------------------------------------
    // 次のページに進む
    public void toAdvanceEditingPage() {
        PageOperationModel pageOperationModel = paintModelContainer.getPageOperationModel();
        PageConnectionModel pageConnectionModel = paintModelContainer.getPageConnectionModel();

        pageOperationModel.incrementPageNo(mCurPageNo, mPageSize.getValue());
        pageConnectionModel.getPage(mCurPageId);
    }

    //-----------------------------------------------------------------
    // 前のページに戻る
    public void toBackEditingPage() {
        PageOperationModel pageOperationModel = paintModelContainer.getPageOperationModel();
        PageConnectionModel pageConnectionModel = paintModelContainer.getPageConnectionModel();

        pageOperationModel.decrementPageNo(mCurPageNo);
        pageConnectionModel.getPage(mCurPageId);
    }

    //-----------------------------------------------------------------
    //-----------------------------------------------------------------
    // ページの追加通信リクエスト
    public void addPageRequest() {
        PageConnectionModel pageConnectionModel = paintModelContainer.getPageConnectionModel();

        pageConnectionModel.addPage();
        pageConnectionModel.getPageSize(mPageSize);
        Log.d("pageSize:", mPageSize.getValue().toString());
    }

    //-----------------------------------------------------------------
    // ページ削除
    public void deletePageRequest() {
        PageConnectionModel pageConnectionModel = paintModelContainer.getPageConnectionModel();
        PageOperationModel pageOperationModel = paintModelContainer.getPageOperationModel();

        pageConnectionModel.deletePage();
        pageConnectionModel.getPageSize(mPageSize);

        //ページ削除後同じページ番号のページを再取得する必要あり
        if (mPageSize.getValue() < mCurPageNo.getValue())
            pageOperationModel.decrementPageNo(mCurPageNo);

        Log.d("pageSize:", mPageSize.getValue().toString());

    }

    //-----------------------------------------------------------------
    //-----------------------------------------------------------------
    //
    public void deleteStroke() {
        this.mStrokes.getValue().clear();
    }

    //-----------------------------------------------------------------
    //
    public void getPageSizeRequest() {
        paintModelContainer.getPageConnectionModel().getPageSize(mPageSize);
    }

    //-----------------------------------------------------------------
    //-----------------------------------------------------------------
    // 一定間隔でサーバー上の筆跡を取得する（GET）
    @Override
    public void run() {
//        Log.d("debug", "run: ");
        paintModelContainer.getPaintConnectionModel().getStrokes(mStrokes);
        paintModelContainer.getPaintConnectionModel().getStrokeNo(mStrokeNo);
        paintModelContainer.getPageConnectionModel().getPageSize(mPageSize);
    }

    //-----------------------------------------------------------------
    //
    public void stop() {
        thread.shutdown();
    }
    //-----------------------------------------------------------------
}