package com.axzae.homeassistant;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.database.ContentObserver;
import android.graphics.Color;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.customtabs.CustomTabsIntent;
import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.NavigationView;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.PopupMenu;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.axzae.homeassistant.fragment.ConnectionFragment;
import com.axzae.homeassistant.fragment.EntityFragment;
import com.axzae.homeassistant.model.Changelog;
import com.axzae.homeassistant.model.Entity;
import com.axzae.homeassistant.model.ErrorMessage;
import com.axzae.homeassistant.model.Group;
import com.axzae.homeassistant.model.HomeAssistantServer;
import com.axzae.homeassistant.model.MDIFont;
import com.axzae.homeassistant.model.rest.CallServiceRequest;
import com.axzae.homeassistant.model.rest.RxPayload;
import com.axzae.homeassistant.provider.DatabaseManager;
import com.axzae.homeassistant.provider.DummyContentProvider;
import com.axzae.homeassistant.provider.EntityContentProvider;
import com.axzae.homeassistant.provider.ServiceProvider;
import com.axzae.homeassistant.service.DataSyncService;
import com.axzae.homeassistant.util.BottomNavigationViewHelper;
import com.axzae.homeassistant.shared.EntityProcessInterface;
import com.axzae.homeassistant.shared.EventEmitterInterface;
import com.axzae.homeassistant.util.CommonUtil;
import com.axzae.homeassistant.util.FaultUtil;
import com.axzae.homeassistant.view.ChangelogView;
import com.axzae.homeassistant.view.MultiSwipeRefreshLayout;
import com.crashlytics.android.Crashlytics;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;
import com.google.android.gms.ads.MobileAds;
import com.jaeger.library.StatusBarUtil;
import com.miguelcatalan.materialsearchview.MaterialSearchView;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.PublishSubject;
import io.reactivex.subjects.Subject;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class MainActivity extends BaseActivity implements BottomNavigationView.OnNavigationItemSelectedListener, EntityProcessInterface, EventEmitterInterface {
    private Subject<RxPayload> mEventEmitter = PublishSubject.create();
    private Call<String> mCall2;
    private Spinner mServerSpinner;
    private int spinnerCheck = 0;
    private ArrayList<HomeAssistantServer> mServers;
    private ServerAdapter mServerAdapter;
    private AppBarLayout mAppBarLayout;

    @Override
    public Subject<RxPayload> getEventSubject() {
        return mEventEmitter;
    }

    //Cursor Loader
    private EntityChangeObserver mEntityChangeObserver;

    private SharedPreferences mSharedPref;

    private HomeAssistantServer mCurrentServer;
    private ProgressBar mProgressBar;
    private RefreshTask mRefreshTask;
    private Call<ArrayList<Entity>> mCall;
    private boolean doubleBackToExitPressedOnce;
    private MultiSwipeRefreshLayout mSwipeRefresh;
    private DrawerLayout mDrawerLayout;
    private NavigationView mNavigationView;

    private Toast mToast;
    private boolean runonce = false;

    private BottomNavigationView mNavigation;
    private MaterialSearchView mSearchView;
    private MenuItem mMenuHoursand;

    private ViewPagerAdapter mViewPagerAdapter;
    private ViewPager mViewPager;

    //Data
    private ArrayList<Group> mGroups;

    //Bound Service (Experimental)
    private DataSyncService mService;
    private boolean mBound;
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            // We've bound to LocalService, cast the IBinder and get LocalService instance
            DataSyncService.LocalBinder binder = (DataSyncService.LocalBinder) service;
            mService = binder.getService();
            mBound = true;

            if (mSharedPref.getBoolean("websocket_mode", true)) {
                mService.startWebSocket(mCurrentServer, true);
            }


            Log.d("YouQi", "Service Bound");
            binder.getEventSubject()
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Observer<RxPayload>() {
                        @Override
                        public void onSubscribe(Disposable d) {

                        }

                        @Override
                        public void onNext(RxPayload rxPayload) {
                            mEventEmitter.onNext(rxPayload);
                        }

                        @Override
                        public void onError(Throwable e) {

                        }

                        @Override
                        public void onComplete() {

                        }
                    });


        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };


    private void showNetworkBusy() {
        mProgressBar.setVisibility(View.VISIBLE);
    }

    private void showNetworkIdle() {
        mProgressBar.setVisibility(View.GONE);
    }

    private void showDatabaseBusy() {
        if (mMenuHoursand != null) mMenuHoursand.setVisible(true);
    }

    private void showDatabaseIdle() {
        if (mMenuHoursand != null) mMenuHoursand.setVisible(false);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_main, menu);

        CommonUtil.setMenuDrawableColor(this, menu.findItem(R.id.action_edit), R.color.md_white_1000);
        CommonUtil.setMenuDrawableColor(this, menu.findItem(R.id.action_refresh), R.color.md_white_1000);
        CommonUtil.setMenuDrawableColor(this, menu.findItem(R.id.action_sort), R.color.md_white_1000);
        CommonUtil.setMenuDrawableColor(this, menu.findItem(R.id.action_webui), R.color.md_white_1000);
        CommonUtil.setMenuDrawableColor(this, menu.findItem(R.id.action_hoursand), R.color.md_white_1000);

        Log.d("YouQi", "onCreateOptionsMenu");
        mMenuHoursand = menu.findItem(R.id.action_hoursand);
        //mSearchView.setMenuItem(mMenuSearch);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setupContentObserver();
        mSharedPref = getAppController().getSharedPref();
        mServers = DatabaseManager.getInstance(this).getConnections();
        //mCurrentServer = HomeAssistantServer.newInstance(mSharedPref);
        mCurrentServer = mServers.get(mSharedPref.getInt("connectionIndex", 0));
        mProgressBar = findViewById(R.id.progressBar);

        Crashlytics.log(Log.DEBUG, "YouQi", mCurrentServer.getBaseUrl());
        Log.d("YouQi", "onCreate");

        setupToolbar();
        setupDrawer();
        setupViewPager();
        setupBottomNavigation();
        setupSearchView();
        setupWhatsNew();

        mProgressBar.setVisibility(View.GONE);

    }

    //https://stackoverflow.com/questions/21380914/contentobserver-onchange
    private void setupContentObserver() {
        // creates and starts a new thread set up as a looper
        HandlerThread thread = new HandlerThread("COHandlerThread");
        thread.start();

        // creates the handler using the passed looper
        Handler handler = new Handler(thread.getLooper());
        mEntityChangeObserver = new EntityChangeObserver(handler);
    }

    private void setupSearchView() {
        mSearchView = findViewById(R.id.search_view);
        mSearchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
            @Override
            public boolean onQueryTextSubmit(String query) {
                getCurrentEntityFragment().search(query);
                return false;
            }

            @Override
            public boolean onQueryTextChange(String newText) {
                //Do some magic
                Log.d("YouQi", "onQueryTextChange: " + newText);
                return false;
            }
        });

        mSearchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener() {
            @Override
            public void onSearchViewShown() {
                //Do some magic
                Log.d("YouQi", "onSearchViewShown");
            }

            @Override
            public void onSearchViewClosed() {
                Log.d("YouQi", "onSearchViewClosed");
                //Do some magic
            }
        });
    }

    private void setupToolbar() {
        final Toolbar toolbar = findViewById(R.id.toolbar);
        mAppBarLayout = findViewById(R.id.appbar);
        setSupportActionBar(toolbar);
        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayHomeAsUpEnabled(false);
            getSupportActionBar().setTitle(getString(R.string.app_name));
            //getSupportActionBar().setSubtitle(mFullUri);
        }
    }

    private void setupDrawer() {
        mDrawerLayout = findViewById(R.id.drawer_layout);
        mNavigationView = findViewById(R.id.nav_view);
        final TextView mVersionText = findViewById(R.id.version_text);
        final View mHeaderView = mNavigationView.getHeaderView(0);

        try {
            PackageInfo packageInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
            String summary = String.format(Locale.ENGLISH, "v%s", packageInfo.versionName);
            mVersionText.setText(summary);
        } catch (Exception e) {
            mVersionText.setText("");
        }


        final View mProfileImage = mHeaderView.findViewById(R.id.profile_image);
        CommonUtil.setBouncyTouch(mProfileImage);

        final TextView websocketButton = mHeaderView.findViewById(R.id.text_websocket);
        websocketButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mService.startWebSocket(mCurrentServer);
            }
        });


        //TextView mainText = mHeaderView.findViewById(R.id.main_text);
        //TextView subText = mHeaderView.findViewById(R.id.sub_text);
        //mainText.setText(getString(R.string.app_name));
        //subText.setText(mFullUri);

        mServerSpinner = mHeaderView.findViewById(R.id.spinner_server);
        //servers.add(new HomeAssistantServer(mCurrentServer.getBaseUrl(), mCurrentServer.getPassword()));
        mServerAdapter = new ServerAdapter(this, 0, mServers);
        mServerSpinner.setAdapter(mServerAdapter);
        mServerSpinner.setSelection(mSharedPref.getInt("connectionIndex", 0), false); //must
        mServerSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> adapterView, View view, int pos, long id) {
                if (++spinnerCheck <= 1) return;

                Log.d("YouQi", "mServerSpinner selected: " + pos);
                mSharedPref.edit().putInt("connectionIndex", pos).apply();
                switchConnection(mServers.get(pos));
//                HomeAssistantServer mServer = (HomeAssistantServer) mServerAdapter.getSelectedItem();
//                if (mServer == null) {
//                    logOut();
//                    return;
//                }
                //setTitle(CommonUtil.getPrintableMSISDN(mSubscriber.msisdn));
                //getSupportActionBar().setSubtitle(mSubscriber.primaryOfferName);
                //getSupportActionBar().setSubtitle(CommonUtil.getPrintableMSISDN(mSubscriber.msisdn));
                mDrawerLayout.closeDrawers();
            }

            @Override
            public void onNothingSelected(AdapterView<?> adapterView) {

            }
        });


        //Hack in place to make blurdialogfragment statusbar height calculation works
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window w = getWindow(); // in Activity's onCreate() for instance
            //w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION, WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
            w.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }


        //StatusBar Scrim
        StatusBarUtil.setColorForDrawerLayout(this, mDrawerLayout, ResourcesCompat.getColor(getResources(), R.color.md_red_500, null), 128);

        ViewGroup contentView = findViewById(android.R.id.content);
        View fakeTranslucentView = contentView.findViewById(com.jaeger.library.R.id.statusbarutil_translucent_view);
        if (fakeTranslucentView != null) {
            if (fakeTranslucentView.getVisibility() == View.GONE) {
                fakeTranslucentView.setVisibility(View.VISIBLE);
            }
            String colorString = "#" + Integer.toHexString(128) + Integer.toHexString(ResourcesCompat.getColor(getResources(), R.color.colorPrimaryDarkBeforeAlpha50, null)).substring(2);
            Log.d("YouQi", "colorString: " + colorString);
            fakeTranslucentView.setBackgroundColor(Color.parseColor(colorString));
        }

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, mDrawerLayout, (Toolbar) findViewById(R.id.toolbar), R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        mDrawerLayout.addDrawerListener(toggle);
        toggle.syncState();

        mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                boolean isSelected = false;
                switch (item.getItemId()) {
                    case R.id.nav_webui:
                        showWebUI();
                        break;
                    case R.id.nav_ads:
                        watchAds();
                        break;
                    case R.id.nav_logbook:
                        showLogbook();
                        break;
                    case R.id.nav_map:
                        showMap();
                        break;
                    case R.id.nav_help:
                        showWiki();
                        mDrawerLayout.closeDrawers();
                        break;
                    case R.id.nav_settings:
                        showSettings();
                        mDrawerLayout.closeDrawers();
                        break;
                    case R.id.nav_share:
                        shareApp();
                        break;
                    case R.id.nav_bug_report:
                        sendBugReport();
                        mDrawerLayout.closeDrawers();
                        //overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
                        //overridePendingTransition(R.anim.activity_open_translate, R.anim.activity_close_scale);
                        //isSelected = true;
                        break;

                    case R.id.nav_logout:
                        showSwitch();
                        mDrawerLayout.closeDrawers();
                        break;

                    default:
                        isSelected = true;
                }
                return isSelected;
            }
        });

    }

    private void switchConnection(HomeAssistantServer homeAssistantServer) {
        mCurrentServer = homeAssistantServer;
        if (mSharedPref.getBoolean("websocket_mode", true)) {
            mService.stopWebSocket();
            mService.startWebSocket(mCurrentServer);
        }
    }

    private void showLogbook() {
        Intent intent = new Intent(MainActivity.this, LogbookActivity.class);
        intent.putExtra("server", CommonUtil.deflate(mCurrentServer));
        startActivity(intent);
        overridePendingTransition(R.anim.activity_open_translate, R.anim.activity_close_scale);
    }

    private void showMap() {
        Intent intent = new Intent(MainActivity.this, MapActivity.class);
        intent.putExtra("server", CommonUtil.deflate(mCurrentServer));
        startActivity(intent);
        overridePendingTransition(R.anim.activity_open_translate, R.anim.activity_close_scale);
    }

    private void shareApp() {
        Intent sendIntent = new Intent();
        sendIntent.setAction(Intent.ACTION_SEND);
        sendIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.message_recommendation, "https://goo.gl/5rkPnP  #homeassistant #android"));
        sendIntent.setType("text/plain");
        startActivity(sendIntent);
    }

    private void watchAds() {
        MobileAds.initialize(getApplicationContext(), getString(R.string.banner_ad_app_id));
        AdView mAdView = findViewById(R.id.adView);
        mAdView.loadAd(CommonUtil.getAdRequest());
    }

    private void setupViewPager() {
        TabLayout mTabLayout = findViewById(R.id.tabs);
        mViewPager = findViewById(R.id.viewpager);

        mViewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());

        mGroups = DatabaseManager.getInstance(this).getGroups();
        for (Group group : mGroups) {
            if (group.groupId == 1) {
                group.groupName = getString(R.string.title_home);
            }
            mViewPagerAdapter.addFragment(EntityFragment.getInstance(group), group.getFriendlyName());
        }
        mViewPager.setAdapter(mViewPagerAdapter);
        mViewPager.setOffscreenPageLimit(20);

        mTabLayout.setupWithViewPager(mViewPager);
        mTabLayout.setSelectedTabIndicatorHeight(CommonUtil.pxFromDp(this, 4f));
        for (int i = 0; i < mGroups.size(); ++i) {
            Group group = mGroups.get(i);
            if (group.hasMdiIcon()) {
                TabLayout.Tab currentTab = mTabLayout.getTabAt(i);
                if (currentTab != null) {
                    View tab = LayoutInflater.from(this).inflate(R.layout.custom_tab, mTabLayout, false);
                    TextView mdiText = tab.findViewById(R.id.text_mdi);
                    TextView nameText = tab.findViewById(R.id.text_name);
                    mdiText.setText(MDIFont.getIcon(group.attributes.icon));
                    nameText.setText(group.getFriendlyName());
                    currentTab.setCustomView(tab);
                }
            }
        }

        mTabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager) {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                super.onTabSelected(tab);
                ActionBar actionBar = getSupportActionBar();
                if (actionBar != null) {
                    actionBar.setTitle(tab.getPosition() == 0 ? getString(R.string.app_name) : tab.getText());
                }

                showBottomNavigation();
                //numTab = tab.getPosition();
                //prefs.edit().putInt("numTab", numTab).apply();
            }
        });
    }

    public void showBottomNavigation() {
        mNavigation.clearAnimation();
        mNavigation.animate().translationY(0).setDuration(200);
    }

    private void setupBottomNavigation() {
        mSwipeRefresh = findViewById(R.id.swipe_refresh_layout);
        mSwipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshApi();
            }
        });
        mSwipeRefresh.setSwipeableChildren(mViewPager);

        mNavigation = findViewById(R.id.navigation);
        mNavigation.setOnNavigationItemSelectedListener(this);
        mNavigation.setSelectedItemId(-1);
        mNavigation.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        Log.d("YouQi", "navigation: " + mNavigation.getMeasuredHeight());
        //CoordinatorLayout.LayoutParams params = new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT);
        //params.setMargins(0, 0, 0, mNavigation.getMeasuredHeight());  // left, top, right, bottom

        //CoordinatorLayout.LayoutParams params2 = (CoordinatorLayout.LayoutParams) mSwipeRefresh.getLayoutParams();
        //Log.d("YouQi", "Margin: " + params2.leftMargin + ", " + params2.topMargin + ", " + params2.rightMargin + ", " + mNavigation.getMeasuredHeight());
        //params2.setMargins(params2.leftMargin, params2.topMargin, params2.rightMargin, mNavigation.getMeasuredHeight());
        //mSwipeRefresh.setLayoutParams(params2);
        BottomNavigationViewHelper.disableShiftMode(mNavigation);
        //Log.d("YouQi", "FULL URI: " + mSharedPref.getString(ConnectActivity.EXTRA_FULL_URI, null));

        //CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mNavigation.getLayoutParams();
        //layoutParams.setBehavior(new BottomNavigationViewBehavior());
    }

    private void setupWhatsNew() {
        final String prefKey = "whatsnew" + BuildConfig.VERSION_CODE;

        Changelog changelog = Changelog.getLatest();
        ChangelogView changelogView = new ChangelogView(this);
        changelogView.loadLogs(changelog.logs);
        new MaterialDialog.Builder(this)
                .title("Community Edition")
                .customView(changelogView, true)
                .positiveText(getString(R.string.action_gotit))
                .positiveColorRes(R.color.md_blue_500)
                .show();
    }

    @Override
    protected void onStart() {
        super.onStart();

        Intent intent = new Intent(this, DataSyncService.class);
        getApplicationContext().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        Log.d("YouQi", "Destroying MainActivity");

        if (mBound) {
            getApplicationContext().unbindService(mConnection);
            mBound = false;
        }

        mEventEmitter.onComplete();
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {

            case R.id.action_refresh:
                refreshApi();
                return true;

            case R.id.action_edit:
                showEdit(null);
                return true;

            case R.id.action_sort:
                showSortOptions();
                return true;

            case android.R.id.home:
                onBackPressed();
                return true;

            case R.id.action_settings:
                showSettings();
                return true;

            case R.id.action_clear_search:
                clearSearch();
                return true;
            case R.id.action_webui:
                showWebUI();
                return true;

            case R.id.action_switch:
                showSwitch();
                return true;

            //case R.id.action_logout:
            //    logOut();
            //    return true;
        }

        return super.onOptionsItemSelected(item);
    }

    private void clearSearch() {
        getCurrentEntityFragment().clearSearch();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case 2000: {
                if (resultCode == Activity.RESULT_OK) {
                    mEventEmitter.onNext(RxPayload.getInstance("SETTINGS"));
                }
                break;
            }

            case 2001: {
                if (resultCode == Activity.RESULT_OK) {
                    clearSearch();

                    Group group = CommonUtil.inflate(data.getStringExtra("group"), Group.class);
                    Log.d("YouQi", "Received Group:" + group.groupId);

                    RxPayload payload = RxPayload.getInstance("EDIT");
                    payload.group = group;
                    mEventEmitter.onNext(payload);
                    //Toast.makeText(this, "OK!", Toast.LENGTH_SHORT).show();
                    //getContentResolver().notifyChange(EntityContentProvider.getUrl(), null);
                }
                break;
            }
        }
    }

    private void showSettings() {
        Intent i = new Intent(this, SettingsActivity.class);
        //i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivityForResult(i, 2000);
        overridePendingTransition(R.anim.activity_open_translate, R.anim.activity_close_scale);
    }

    private void showWiki() {
        Intent i = new Intent(this, WikiActivity.class);
        //i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
        startActivity(i);
        overridePendingTransition(R.anim.activity_open_translate, R.anim.activity_close_scale);
    }

    private void sendBugReport() {

        new MaterialDialog.Builder(this)
                .title(R.string.pref_bug_report)
                .content(R.string.message_attach_bootstrap)
                .positiveText(getString(R.string.action_yes))
                .negativeText(getString(R.string.action_no))
                .negativeColorRes(R.color.md_blue_500)
                .positiveColorRes(R.color.md_blue_500)
                .onNegative(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        sendBugReport(null);
                    }
                })
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {

                        if (mCall2 == null) {
                            showNetworkBusy();
                            mCall2 = ServiceProvider.getRawApiService(mCurrentServer.getBaseUrl()).rawStates(mCurrentServer.getPassword());
                            mCall2.enqueue(new Callback<String>() {
                                @Override
                                public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
                                    mCall2 = null;
                                    showNetworkIdle();

                                    if (FaultUtil.isRetrofitServerError(response)) {
                                        showError(response.message());
                                        return;
                                    }

                                    File bootstrapFile = CommonUtil.writeToExternalCache(MainActivity.this, "states.json", response.body());
                                    Uri uri = Uri.fromFile(bootstrapFile);
                                    sendBugReport(uri);
                                }

                                @Override
                                public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
                                    mCall2 = null;
                                    showNetworkIdle();
                                    showError(FaultUtil.getPrintableMessage(MainActivity.this, t));
                                }
                            });
                        }


                    }
                })
                .show();


    }

    private void sendBugReport(Uri uri) {
        Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
        emailIntent.setData(Uri.parse("mailto:"));
        emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[]{"[email protected]"});
        emailIntent.putExtra(Intent.EXTRA_SUBJECT, "HomeAssist Bug Report");
        emailIntent.putExtra(Intent.EXTRA_TEXT, "\n\nAndroid Version: " + Build.VERSION.RELEASE + "\nHomeAssist Version: " + BuildConfig.VERSION_NAME);
        if (uri != null) {
            emailIntent.putExtra(Intent.EXTRA_STREAM, uri);
        }
        startActivity(Intent.createChooser(emailIntent, getString(R.string.title_send_email)));
    }

    private void showSwitch() {
        new MaterialDialog.Builder(this)
                .content(getString(R.string.message_signout, mCurrentServer.getBaseUrl()))
                .positiveText(getString(R.string.action_logout))
                .negativeText(getString(R.string.action_cancel))
                .negativeColorRes(R.color.md_blue_500)
                .positiveColorRes(R.color.md_blue_500)
                .onPositive(new MaterialDialog.SingleButtonCallback() {
                    @Override
                    public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                        logOut();
                    }
                })
                .show();
    }

    private void showWebUI() {
        CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
        //builder.setStartAnimations(mActivity, R.anim.right_in, R.anim.left_out);

        builder.setStartAnimations(this, R.anim.activity_open_translate, R.anim.activity_close_scale);
        builder.setExitAnimations(this, R.anim.activity_open_scale, R.anim.activity_close_translate);
        builder.setToolbarColor(ResourcesCompat.getColor(getResources(), R.color.md_blue_500, null));
//        builder.setSecondaryToolbarColor(ResourcesCompat.getColor(getResources(), R.color.md_white_1000, null));
        CustomTabsIntent customTabsIntent = builder.build();

        try {
            customTabsIntent.launchUrl(this, mCurrentServer.getBaseUri());
        } catch (ActivityNotFoundException e) {
            showToast(getString(R.string.exception_no_chrome));
        }
    }

    private void addConnection() {
        //mDrawerLayout.closeDrawers();
        ConnectionFragment fragment = ConnectionFragment.newInstance(null);
        fragment.show(getFragmentManager(), null);
        //Toast.makeText(mService, "add connection", Toast.LENGTH_SHORT).show();
    }

    public void refreshConnections() {
        Log.d("YouQi", "refreshConnections");
        mServers = DatabaseManager.getInstance(this).getConnections();
        mServerAdapter.setItems(mServers);
        mServerAdapter.notifyDataSetChanged();
    }

    @Override
    public void onBackPressed() {
        //super.onBackPressed();

        if (mDrawerLayout.isDrawerOpen(mNavigationView)) {
            mDrawerLayout.closeDrawers();
        } else if (mSearchView.isSearchOpen()) {
            mSearchView.closeSearch();
        } else if (getCurrentEntityFragment().isFilterState()) {
            getCurrentEntityFragment().clearSearch();
        } else {
            if (doubleBackToExitPressedOnce) {
                super.onBackPressed();
                return;
            }

            this.doubleBackToExitPressedOnce = true;

            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    doubleBackToExitPressedOnce = false;
                }
            }, 2000);
        }
    }

    public void showError(final String status) {
        Toast.makeText(this, status, Toast.LENGTH_SHORT).show();
    }

    public void refreshApi() {
        if (mRefreshTask == null) {
            mRefreshTask = new RefreshTask();
            mRefreshTask.execute((Void) null);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        getContentResolver().unregisterContentObserver(mEntityChangeObserver);
    }

    @Override
    protected void onResume() {
        super.onResume();
        getContentResolver().registerContentObserver(DummyContentProvider.getUrl(), true, mEntityChangeObserver);
        if (!runonce || (mService != null && !mService.isWebSocketRunning())) {
            runonce = true;
            refreshApi();
        }
    }

    @Override
    public void callService(final String domain, final String service, CallServiceRequest serviceRequest) {
        if (mService != null && mService.isWebSocketRunning()) {
            Log.d("YouQi", "Using WebSocket");
            mService.callService(domain, service, serviceRequest);
        } else if (mCall == null) {
            Log.d("YouQi", "Using HTTP");
            showNetworkBusy();
            Crashlytics.log("baseUrl: " + mCurrentServer.getBaseUrl());
            mCall = ServiceProvider.getApiService(mCurrentServer.getBaseUrl()).callService(mCurrentServer.getPassword(), domain, service, serviceRequest);
            mCall.enqueue(new Callback<ArrayList<Entity>>() {
                @Override
                public void onResponse(@NonNull Call<ArrayList<Entity>> call, @NonNull Response<ArrayList<Entity>> response) {
                    mCall = null;
                    showNetworkIdle();

                    if (FaultUtil.isRetrofitServerError(response)) {
                        showError(response.message());
                        return;
                    }

                    ArrayList<Entity> restResponse = response.body();
                    CommonUtil.logLargeString("YouQi", "service restResponse: " + CommonUtil.deflate(restResponse));

                    if ("script".equals(domain) || ("automation".equals(domain) || "scene".equals(domain) || "trigger".equals(service))) {
                        showToast(getString(R.string.toast_triggered));
                    }

                    if (restResponse != null) {
                        for (Entity entity : restResponse) {
                            getContentResolver().update(Uri.parse("content://com.axzae.homeassistant.provider.EntityContentProvider/"), entity.getContentValues(), "ENTITY_ID='" + entity.entityId + "'", null);
                        }

                        //RxPayload payload = RxPayload.getInstance("UPDATE_ALL");
                        //payload.entities = restResponse;
                        //mEventEmitter.onNext(payload);
                    }

                }

                @Override
                public void onFailure(@NonNull Call<ArrayList<Entity>> call, @NonNull Throwable t) {
                    mCall = null;
                    showNetworkIdle();
                    showError(FaultUtil.getPrintableMessage(MainActivity.this, t));
                }
            });
        }

        //ContentValues values = new ContentValues();
        //values.put(HabitTable.TIME); //whatever column you want to update, I dont know the name of it
        //getContentResolver().update(HabitTable.CONTENT_URI,values,HabitTable.ID+"=?",new String[] {String.valueOf(id)}); //id is the id of the row you wan to update
        //getContentResolver().update()
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        showBottomNavigation();
        mAppBarLayout.setExpanded(true);

        switch (item.getItemId()) {

            case R.id.action_search:
                showSearch();
                //doTest();
                break;

            case R.id.action_refresh:
                if (mRefreshTask == null) {
                    mSwipeRefresh.setRefreshing(true);
                }
                refreshApi();
                break;

            case R.id.action_edit:
                showEdit(null);
                break;

            case R.id.action_sort:
                showSortOptions();
                break;

            case R.id.action_switch:
                showSwitch();
                break;
        }

        return false;
    }

    private void showSearch() {
        mSearchView.showSearch(false);
    }

    @Override
    public HomeAssistantServer getServer() {
        return mCurrentServer;
    }

    @Override
    public Context getActivityContext() {
        return this;
    }

    private class RefreshTask extends AsyncTask<Void, String, ErrorMessage> {
        RefreshTask() {
            showNetworkBusy();
            mNavigation.getMenu().findItem(R.id.action_refresh).setEnabled(false);
        }

        @Override
        protected ErrorMessage doInBackground(Void... params) {
            try {
                publishProgress("Connecting");
                Response<ArrayList<Entity>> response = ServiceProvider.getApiService(mCurrentServer.getBaseUrl()).getStates(mCurrentServer.getPassword()).execute();
                if (response.code() != 200) {
                    //OAuthToken token = new Gson().fromJson(response.errorBody().string(), OAuthToken.class);
                    return new ErrorMessage("Error", response.message());
                }

                final ArrayList<Entity> statesResponse = response.body();

                if (statesResponse == null) {
                    throw new RuntimeException("No Data");
                }

                Log.d("YouQi", "bootstrapResponse: " + statesResponse);
                publishProgress("Refreshing");

                ArrayList<ContentValues> values = new ArrayList<>();
                for (Entity entity : statesResponse) {
                    values.add(entity.getContentValues());
                }

                getContentResolver().bulkInsert(EntityContentProvider.getUrl(), values.toArray(new ContentValues[values.size()]));
                publishProgress((String) null);
                //Crashlytics.setUserIdentifier(settings.bootstrapResponse.profile.loginId);

            } catch (Exception e) {
                e.printStackTrace();
                return new ErrorMessage("System Exception", FaultUtil.getPrintableMessage(MainActivity.this, e));
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
            //setStatus(values[0]);
        }

        @Override
        protected void onPostExecute(final ErrorMessage errorMessage) {
            showNetworkIdle();
            mRefreshTask = null;
            mNavigation.getMenu().findItem(R.id.action_refresh).setEnabled(true);
            mSwipeRefresh.setRefreshing(false);

            if (errorMessage != null) {
                showError(errorMessage.message);
            }
        }

        @Override
        protected void onCancelled() {
            showNetworkIdle();
        }
    }

    public void showSortOptions() {
        PopupMenu popup = new PopupMenu(this, ((BottomNavigationMenuView) mNavigation.getChildAt(0)).getChildAt(2));
        //Inflating the Popup using xml file
        popup.getMenuInflater().inflate(R.menu.menu_sort, popup.getMenu());

        //registering popup with OnMenuItemClickListener
        popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
            public boolean onMenuItemClick(MenuItem item) {
                EntityFragment currentFragment = getCurrentEntityFragment();
                Group group = currentFragment.getGroup();
                if (group != null) {
                    currentFragment.sortEntity(item.getOrder());
                }
                return true;
            }
        });

        popup.show();
    }

    public EntityFragment getCurrentEntityFragment() {
        return (EntityFragment) mViewPagerAdapter.getItem(mViewPager.getCurrentItem());
    }

    @Override
    public void showToast(String message) {
        if (mToast != null) {
            mToast.cancel();
        }
        mToast = Toast.makeText(this, message, Toast.LENGTH_SHORT);
        mToast.show();
    }

    public void showEdit(View v) {
        Bundle bundle = new Bundle();
        bundle.putString("group", CommonUtil.deflate(getCurrentEntityFragment().getGroup()));
        Intent i = new Intent(this, EditActivity.class);
        i.putExtras(bundle);
        startActivityForResult(i, 2001);
        overridePendingTransition(R.anim.stay_still, R.anim.fade_out);
    }

    private class ServerAdapter extends ArrayAdapter<HomeAssistantServer> {
        private List<HomeAssistantServer> items;

        ServerAdapter(Context context, int resource, List<HomeAssistantServer> objects) {
            super(context, resource, objects);
            items = objects;
        }

        public void setItems(List<HomeAssistantServer> objects) {
            items = objects;
        }

        @Override
        public int getCount() {
            return 1 + items.size();
        }

        @Override
        public View getDropDownView(int position, View convertView, @NonNull final ViewGroup parent) {
            if (convertView == null) {
                LayoutInflater vi = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                //convertView = vi.inflate(android.R.layout.simple_spinner_dropdown_item, parent, false);
                convertView = vi.inflate(R.layout.item_server_dropdown, parent, false);
            }

            TextView mainText = convertView.findViewById(R.id.main_text);
            TextView subText = convertView.findViewById(R.id.sub_text);

            if (position == items.size()) {
                mainText.setText(TextUtils.concat(
                        CommonUtil.getSpanText(MainActivity.this, " \n", null, 0.2f),
                        CommonUtil.getSpanText(MainActivity.this, "Add Connection…", null, 0.9f),
                        CommonUtil.getSpanText(MainActivity.this, "\n ", null, 0.2f)
                ));
                subText.setVisibility(View.GONE);

                convertView.findViewById(R.id.parent).setClickable(true);
                convertView.findViewById(R.id.parent).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //Toast.makeText(MainActivity.this, "Hello", Toast.LENGTH_SHORT).show();
                        addConnection();
                        View root = parent.getRootView();
                        root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK));
                        root.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK));
                    }
                });
            } else {
                mainText.setText(items.get(position).getName());
                subText.setVisibility(View.VISIBLE);
                subText.setText(items.get(position).getBaseUrl());
                convertView.findViewById(R.id.parent).setClickable(false);
            }

            return convertView;
        }

        @NonNull
        @Override
        public View getView(int position, View convertView, @NonNull ViewGroup parent) {
            if (convertView == null) {
                convertView = View.inflate(getContext(), android.R.layout.simple_list_item_1, null);
            }

            ((TextView) convertView.findViewById(android.R.id.text1)).setText(items.get(position).getLine(getContext()));
            ((TextView) convertView.findViewById(android.R.id.text1)).setTextColor(ResourcesCompat.getColor(getResources(), R.color.md_white_1000, null));
            return convertView;
        }
    }

    private class ViewPagerAdapter extends FragmentPagerAdapter {
        private final List<Fragment> mFragmentList = new ArrayList<>();
        private final List<String> mFragmentTitleList = new ArrayList<>();

        ViewPagerAdapter(FragmentManager manager) {
            super(manager);
        }

        @Override
        public Fragment getItem(int position) {
            return mFragmentList.get(position);
        }

        @Override
        public int getCount() {
            return mFragmentList.size();
        }

        void addFragment(Fragment fragment, String title) {
            mFragmentList.add(fragment);
            mFragmentTitleList.add(title);
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return mFragmentTitleList.get(position);
        }
    }

    public class EntityChangeObserver extends ContentObserver {

        @Override
        public boolean deliverSelfNotifications() {
            return super.deliverSelfNotifications();
        }

        EntityChangeObserver(Handler handler) {
            super(handler);
        }

        @Override
        public void onChange(boolean selfChange) {
            this.onChange(selfChange, null);
        }

        @Override
        public void onChange(boolean selfChange, Uri uri) {
            Log.d("YouQi", "Observer onChange (UIThread? " + (CommonUtil.isUiThread() ? "Yes" : "No") + ") URI: " + (uri == null ? "null" : uri.toString()));
            if (uri == null) return;

            DatabaseManager databaseManager = DatabaseManager.getInstance(MainActivity.this);
            if ("ALL".equals(uri.getLastPathSegment())) {
                RxPayload payload = RxPayload.getInstance("UPDATE_ALL");
                payload.entities = databaseManager.getEntities();
                mEventEmitter.onNext(payload);
            } else {
                Entity entity = databaseManager.getEntityById(uri.getLastPathSegment());

                if (entity != null) {
                    RxPayload payload = RxPayload.getInstance("UPDATE");
                    payload.entity = entity;
                    mEventEmitter.onNext(payload);
                }
            }
        }

    }

}