package com.anikrajc.remote.ui.activity;

import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomSheetBehavior;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.TabLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.CardView;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;

import com.anikrajc.remote.R;
import com.anikrajc.remote.RemoteApplication;
import com.anikrajc.remote.adapter.MovieRecyclerAdapter;
import com.anikrajc.remote.event.GetCurrentListEvent;
import com.anikrajc.remote.event.GetCurrentTabEvent;
import com.anikrajc.remote.event.GetPlayingEvent;
import com.anikrajc.remote.event.GetViewStackEvent;
import com.anikrajc.remote.event.GetVolumeEvent;
import com.anikrajc.remote.event.PingEvent;
import com.anikrajc.remote.event.SearchEvent;
import com.anikrajc.remote.jobs.AnimeListJob;
import com.anikrajc.remote.jobs.ClearSearchJob;
import com.anikrajc.remote.jobs.GetCurrentListJob;
import com.anikrajc.remote.jobs.GetCurrentTabJob;
import com.anikrajc.remote.jobs.GetPlayingJob;
import com.anikrajc.remote.jobs.GetViewStackJob;
import com.anikrajc.remote.jobs.GetVolumeJob;
import com.anikrajc.remote.jobs.MoviesListJob;
import com.anikrajc.remote.jobs.PingJob;
import com.anikrajc.remote.jobs.PressBackJob;
import com.anikrajc.remote.jobs.PressDownJob;
import com.anikrajc.remote.jobs.PressEnterJob;
import com.anikrajc.remote.jobs.PressFullscreenJob;
import com.anikrajc.remote.jobs.PressLeftJob;
import com.anikrajc.remote.jobs.PressRightJob;
import com.anikrajc.remote.jobs.PressUpJob;
import com.anikrajc.remote.jobs.SearchJob;
import com.anikrajc.remote.jobs.SetVolumeJob;
import com.anikrajc.remote.jobs.ShowAboutJob;
import com.anikrajc.remote.jobs.ShowFavouritesJob;
import com.anikrajc.remote.jobs.ShowSettingsJob;
import com.anikrajc.remote.jobs.ShowWatchlistJob;
import com.anikrajc.remote.jobs.ShowsListJob;
import com.anikrajc.remote.jobs.TogglePlayJob;
import com.anikrajc.remote.util.AppRater;
import com.birbit.android.jobqueue.JobManager;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.anikrajc.remote.util.text.TextHelper.isNumeric;

public class Home extends AppCompatActivity implements View.OnClickListener {
    private JobManager jobManager;
    private RecyclerView mRecyclerView;
    private MovieRecyclerAdapter mAdapter;
    private List<Map<String, String>> data;
    private CardView llBottomSheet;
    private FloatingActionButton fab;
    private Handler handler = new Handler();
    private TabLayout tabLayout;
    private double currentVolume = 0;
    private TextView titlePeek, secondaryPeek;
    private int pingFailed = 0;
    private View connectionHolder;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        jobManager = RemoteApplication.getInstance().getJobManager();
        data = new ArrayList<>();
        initViews();
        AppRater.app_launched(this);
        connectionSetup();
    }

    private void connectionSetup() {
        connectionHolder = findViewById(R.id.connectionHolder);
        Button button = (Button) findViewById(R.id.reconnectButton);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(Home.this, ScanActivity.class));
                finish();
            }
        });
    }

    private void startPeriodic() {
        Runnable periodicUpdate = new Runnable() {
            @Override
            public void run() {
                handler.postDelayed(this, 1000);
                jobManager.addJobInBackground(new PingJob());
                jobManager.addJobInBackground(new GetCurrentListJob());
                jobManager.addJobInBackground(new GetViewStackJob());
//                jobManager.addJobInBackground(new GetCurrentListJob());
                Log.e("periodic", "ping, list");
            }
        };
        handler.post(periodicUpdate);

        Runnable periodicUpdateTabs = new Runnable() {
            @Override
            public void run() {
                handler.postDelayed(this, 3000);
                jobManager.addJobInBackground(new GetCurrentTabJob());
                jobManager.addJobInBackground(new GetVolumeJob());
                jobManager.addJobInBackground(new GetPlayingJob());
                Log.e("periodic", "tabs update");
            }
        };
        handler.post(periodicUpdateTabs);
    }

    private void initViews() {
        fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                jobManager.addJobInBackground(new TogglePlayJob());
            }
        });


        mRecyclerView = (RecyclerView) findViewById(R.id.recycler);
        mRecyclerView.setHasFixedSize(true);
        RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(this, 2);
        mRecyclerView.setLayoutManager(mLayoutManager);

        // specify an adapter (see also next example)
        mAdapter = new MovieRecyclerAdapter(data, Home.this);
        mRecyclerView.setAdapter(mAdapter);

        llBottomSheet = (CardView) findViewById(R.id.bottom_sheet);

        // init the bottom sheet behavior
        final BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from(llBottomSheet);
        bottomSheetBehavior.setHideable(false);
        bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
//                fab.animate().scaleX(1 - slideOffset).scaleY(1 - slideOffset).setDuration(0).start();
//                fab.animate().translationY(convertDpToPixel(100, getApplicationContext()) * slideOffset).setDuration(0).start();
//                fab.animate().rotationX(360*slideOffset).setDuration(0).setInterpolator(new Interpolator() {
//                    @Override
//                    public float getInterpolation(float v) {
//                        return 0;
//                    }
//                }).start();
            }
        });
        findViewById(R.id.peepLayout).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_EXPANDED) {
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED);
                } else if (bottomSheetBehavior.getState() == BottomSheetBehavior.STATE_COLLAPSED) {
                    bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
                }
            }
        });

        tabLayout = (TabLayout) findViewById(R.id.tabLayout);
        tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                switch (tab.getPosition()) {
                    case 0:
                        jobManager.addJobInBackground(new MoviesListJob());
                        break;
                    case 1:
                        jobManager.addJobInBackground(new ShowsListJob());
                        break;
                    case 2:
                        jobManager.addJobInBackground(new AnimeListJob());
                        break;
                }
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

        ImageButton centerButton = (ImageButton) findViewById(R.id.centerButton);
        ImageButton backButton = (ImageButton) findViewById(R.id.backButton);
        ImageButton voiceButton = (ImageButton) findViewById(R.id.voiceButton);
        ImageButton leftButton = (ImageButton) findViewById(R.id.leftButton);
        ImageButton rightButton = (ImageButton) findViewById(R.id.rightButton);
        ImageButton upButton = (ImageButton) findViewById(R.id.upButton);
        ImageButton downButton = (ImageButton) findViewById(R.id.downButton);
        ImageButton volumeDownButton = (ImageButton) findViewById(R.id.volumeDownButton);
        ImageButton volumeUpButton = (ImageButton) findViewById(R.id.volumeUpButton);
        ImageButton fullscreenButton = (ImageButton) findViewById(R.id.fullscreenButton);
        centerButton.setOnClickListener(this);
        backButton.setOnClickListener(this);
        voiceButton.setOnClickListener(this);
        leftButton.setOnClickListener(this);
        rightButton.setOnClickListener(this);
        upButton.setOnClickListener(this);
        downButton.setOnClickListener(this);
        volumeUpButton.setOnClickListener(this);
        volumeDownButton.setOnClickListener(this);
        fullscreenButton.setOnClickListener(this);

        titlePeek = (TextView) findViewById(R.id.titlePeek);
        secondaryPeek = (TextView) findViewById(R.id.secondaryPeek);
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(PingEvent event) {
        if (event.getStatus() == 1) {
            try {
                JSONObject result = new JSONObject(event.getResponse() + "");
                result.getJSONObject("result").getString("butterVersion");
                pingFailed = 0;
            } catch (JSONException e) {
                e.printStackTrace();
                pingFailed++;
            }
        } else if (event.getStatus() == 2) pingFailed += 3;


        if (pingFailed > 3) {
            connectionHolder.setVisibility(View.VISIBLE);
        } else {
            connectionHolder.setVisibility(View.GONE);
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(SearchEvent event) {
        if (event.getStatus() == 1) jobManager.addJobInBackground(new GetCurrentListJob());
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(GetVolumeEvent event) {
        if (event.getStatus() != 1) return;
        try {
            JSONObject result = new JSONObject(event.getResponse() + "");
            currentVolume = result.getJSONObject("result").getDouble("volume");
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(GetViewStackEvent event) {
        if (event.getStatus() != 1) return;
        try {
            JSONObject result = new JSONObject(event.getResponse() + "");
            int length = result.getJSONObject("result").getJSONArray("viewstack").length();
            if (result.getJSONObject("result").getJSONArray("viewstack").getString(length - 1).equals("movie-detail")) {
                startActivity(new Intent(Home.this, MovieDetailsActivity.class));
            } else if (result.getJSONObject("result").getJSONArray("viewstack").getString(length - 1).equals("shows-container-contain")) {
                startActivity(new Intent(Home.this, ShowDetails.class));
            } else if (result.getJSONObject("result").getJSONArray("viewstack").getString(length - 1).equals("about")) {

            } else if (result.getJSONObject("result").getJSONArray("viewstack").getString(length - 1).equals("settings-container-contain")) {

            }


        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(GetPlayingEvent event) {
        if (event.getStatus() != 1) return;
        try {
            JSONObject result = new JSONObject(event.getResponse() + "");
            if (result.getJSONObject("result").has("title") && result.getJSONObject("result").has("quality") && result.getJSONObject("result").has("duration")) {
                String title = result.getJSONObject("result").getString("title");
                String quality = result.getJSONObject("result").getString("quality");
                String duration = "" + ((int) (result.getJSONObject("result").getDouble("duration") / 60));
                titlePeek.setText(title);
                secondaryPeek.setText(quality + "   " + duration + "mins");
            } else {
                titlePeek.setText("No video playing.");
                secondaryPeek.setText("Scroll up to access remote.");
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(GetCurrentTabEvent event) {
        if (event.getStatus() != 1) return;
        try {
            JSONObject result = new JSONObject(event.getResponse() + "");
            String tab = result.getJSONObject("result").getString("tab");
            if (tab.equals("movies")) {
                tabLayout.getTabAt(0).select();
            } else if (tab.equals("shows")) {
                tabLayout.getTabAt(1).select();
            } else if (tab.equals("anime")) {
                tabLayout.getTabAt(2).select();
            } else if (tab.equals("Watchlist")) {

            } else if (tab.equals("Favorites")) {

            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(GetCurrentListEvent event) {
        if (event.getStatus() != 1) return;
        try {
            JSONObject result = new JSONObject(event.getResponse() + "");
            JSONArray list = result.getJSONObject("result").getJSONArray("list");
            data.clear();

            for (int i = 0; i < list.length(); i++) {
                try {
                    Map<String, String> map = new HashMap<>();
                    JSONObject movie = list.getJSONObject(i);
                    String image = "";
                    if (movie.has("image"))
                        image = movie.getString("image");
                    else
                        image = movie.getJSONObject("images").getString("poster");
                    String rating = movie.getString("rating");
                    String year = movie.getString("year");

                    if (!isNumeric(rating)) {
                        rating = movie.getJSONObject("rating").getString("percentage");
                        if (!isNumeric(rating)) {
                            rating = "";
                        } else {
                            rating = "" + (Double.parseDouble(rating) / 10);
                        }
                    }

                    map.put("rating", rating);
                    map.put("image", image);
                    map.put("year", year);
                    data.add(map);
                } catch (JSONException ee) {
                    ee.printStackTrace();
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        mAdapter.notifyDataSetChanged();

    }


    @Override
    public void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
        startPeriodic();
    }

    @Override
    public void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
        handler.removeCallbacksAndMessages(null);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.home, menu);
        MenuItem searchItem = menu.findItem(R.id.search);
        SearchManager searchManager = (SearchManager) Home.this.getSystemService(Context.SEARCH_SERVICE);

        SearchView searchView = null;
        if (searchItem != null) {
            searchView = (SearchView) searchItem.getActionView();
        }
        if (searchView != null) {
            searchView.setSearchableInfo(searchManager.getSearchableInfo(Home.this.getComponentName()));
        }

        searchView.setOnCloseListener(new SearchView.OnCloseListener() {
            @Override
            public boolean onClose() {
                jobManager.addJobInBackground(new ClearSearchJob());
                return false;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.settings:
                jobManager.addJobInBackground(new ShowSettingsJob());
                return true;
            case R.id.favourite:
                jobManager.addJobInBackground(new ShowFavouritesJob());
                return true;
            case R.id.watchlist:
                jobManager.addJobInBackground(new ShowWatchlistJob());
                return true;
            case R.id.about:
                jobManager.addJobInBackground(new ShowAboutJob());
                return true;
            case R.id.scan:
                startActivity(new Intent(Home.this, ScanActivity.class));
                finish();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            String query = intent.getStringExtra(SearchManager.QUERY);
            jobManager.addJobInBackground(new SearchJob(query));
        }
    }


    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.centerButton:
                jobManager.addJobInBackground(new PressEnterJob());
                break;
            case R.id.backButton:
                jobManager.addJobInBackground(new PressBackJob());
                break;
            case R.id.voiceButton:
                break;
            case R.id.upButton:
                jobManager.addJobInBackground(new PressUpJob());
                break;
            case R.id.downButton:
                jobManager.addJobInBackground(new PressDownJob());
                break;
            case R.id.leftButton:
                jobManager.addJobInBackground(new PressLeftJob());
                break;
            case R.id.rightButton:
                jobManager.addJobInBackground(new PressRightJob());
                break;
            case R.id.fullscreenButton:
                jobManager.addJobInBackground(new PressFullscreenJob());
                break;
            case R.id.volumeUpButton:
                currentVolume += 0.1;
                if (currentVolume >= 1) currentVolume = 1;
                jobManager.addJobInBackground(new SetVolumeJob(currentVolume));
                break;
            case R.id.volumeDownButton:
                currentVolume -= 0.1;
                if (currentVolume <= 0) currentVolume = 0;
                jobManager.addJobInBackground(new SetVolumeJob(currentVolume));
                break;
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
            Toast.makeText(this, "Volume Up", Toast.LENGTH_LONG).show();
            currentVolume += 0.1;
            if (currentVolume >= 1) currentVolume = 1;
            jobManager.addJobInBackground(new SetVolumeJob(currentVolume));
            return true;
        }

        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
            Toast.makeText(this, "Volume Down", Toast.LENGTH_LONG).show();
            currentVolume -= 0.1;
            if (currentVolume <= 0) currentVolume = 0;
            jobManager.addJobInBackground(new SetVolumeJob(currentVolume));
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }
}