package it.michelelacorte.iptvfree;


import android.Manifest;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.speech.RecognizerIntent;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.NavigationView;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
import android.widget.Toast;

import com.miguelcatalan.materialsearchview.MaterialSearchView;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.w3c.dom.Document;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import it.michelelacorte.iptvfree.fragment.FragmentIPTV;
import it.michelelacorte.iptvfree.fragment.FragmentIPTVFavorite;
import it.michelelacorte.iptvfree.sd_reader.OnHandleFileListener;
import it.michelelacorte.iptvfree.util.BugReport;
import it.michelelacorte.iptvfree.util.FirstRun;
import it.michelelacorte.iptvfree.util.SharedPreference;
import it.michelelacorte.iptvfree.util.Utils;
import it.michelelacorte.iptvfree.util.ViewPagerAdapter;

@SuppressWarnings("all")
public class MainActivity extends AppCompatActivity  implements View.OnClickListener {

    /**
     * Floatin Action Button menĂ¹ object
     */
    public static Boolean isFabOpen = false;
    public static FloatingActionButton fabMenu,fabAdd,fabDownload;
    public static Animation fab_open,fab_close,rotate_forward,rotate_backward;
    public static TextView labelAdd, labelDownload;

    /**
     * Layout object
     */
    private TabLayout tabLayout;
    private ViewPager viewPager;
    private ActionBarDrawerToggle mDrawerToggle;
    private DrawerLayout drawerLayout;
    private static Handler handler = new Handler();
    private static Runnable myrunnable;
    private ProgressDialog ringProgressDialog;
    private ProgressDialog mProgressDialog;
    private CoordinatorLayout coordinatorLayout;
    public static ViewPagerAdapter adapter;
    private Toolbar toolbar;
    private MaterialSearchView searchView;
    private MenuItem item;
    /**
     * List of data catched from m3u file
     */
    public static List<String> categoryName = new ArrayList<>();
    public static List<String> channelName = new ArrayList<>();
    public static List<String> channelLink = new ArrayList<>();
    public static List<Integer> categorySize = new ArrayList<>();
    //Favorite
    public static ArrayList<String> favoriteName = new ArrayList<>();
    public static ArrayList<String> favoriteLink = new ArrayList<>();
    //Personal List
    public static List<String> categoryNamePersonal = new ArrayList<>();
    public static List<String> channelNamePersonal = new ArrayList<>();
    public static List<String> channelLinkPersonal = new ArrayList<>();
    public static List<Integer> categorySizePersonal = new ArrayList<>();
    private static List<String> state;
    /**
     * Other variable
     */
    private String [] channelNameArray;
    private boolean isFavorite = false;
    public static int CATEGORY = 0;
    public static int CATEGORY_INDEX = 0;
    public static boolean DEFAULT = true;
    public static boolean isMyListLoadedFromPath = false;
    public static boolean isMyListLoadedFromURL = false;
    private String URL = null;
    private static final String TAG = "MainActivity";
    private static final int REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSIONS = 100;
    private SharedPreference preferencesIPTV = new SharedPreference();


    /**
     * This class extends AsyncTask and implements code for getting data from URL
     */
    private class GetDataAsync extends AsyncTask<String, Void, Boolean> {
        ProgressDialog ringProgressDialog;
        Activity activity;

        public GetDataAsync(Activity activity)
        {
            this.activity = activity;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            ringProgressDialog = ProgressDialog.show(activity, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
            ringProgressDialog.setCancelable(false);
        }


        @Override
        protected Boolean doInBackground(String... url) {
            try{
                try {
                    DefaultHttpClient httpclient = new DefaultHttpClient();
                    HttpGet httppost = new HttpGet(url[0]);
                    HttpResponse response = null;
                    response = httpclient.execute(httppost);
                    HttpEntity ht = response.getEntity();
                    BufferedHttpEntity buf = new BufferedHttpEntity(ht);
                    InputStream is = buf.getContent();
                    BufferedReader br = new BufferedReader(new InputStreamReader(is));
                    String inputLine = null;
                    try {
                        inputLine = br.readLine();
                        boolean dummyLink = false;
                        int j = 0;
                        int line = 0;
                        while ((inputLine = br.readLine()) != null){
                            String st = inputLine.toString();
                            line++;
                            if(st.equalsIgnoreCase("<List>") || st.equalsIgnoreCase("</List>") || st.equalsIgnoreCase("#EXTM3U"))
                            {
                                //Not relevant line, decrease.
                                line--;
                            }
                            if(st.startsWith("http") || st.startsWith("rtmp") || st.startsWith("rtsp") || st.startsWith("mmsh")){
                                if(dummyLink) {
                                    dummyLink = false;
                                }else{
                                    j++;
                                    channelLink.add(st);
                                }
                            }
                            String dump = st;
                            for (int i=0; i<st.length()-1; i++){
                                if(st.charAt(i)==','){
                                    String afterComma = dump.replaceAll(".*,", "").trim();
                                    if(!Character.isLetterOrDigit(afterComma.charAt(0))){
                                        Pattern pattern = Pattern.compile("[^a-z A-Z]");
                                        Matcher matcher = pattern.matcher(afterComma);
                                        categoryName.add(matcher.replaceAll(""));
                                        dummyLink = true;
                                        if(line > 1) {
                                            categorySize.add(j);
                                        }
                                    }else if(Character.isLetterOrDigit(afterComma.charAt(0))){
                                        channelName.add(afterComma);
                                    }
                                }
                            }
                        }
                        categorySize.add(j);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }catch(Exception e) {
                Log.e(TAG, "Data Async: " + e);
            }
            return true;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            super.onPostExecute(success);
            ringProgressDialog.dismiss();
        }
    }

    /**
     * This class extends AsyncTask and implements code for getting data from URL (specifically for Personal Data)
     */
    private class GetDataAsyncPersonal extends AsyncTask<String, Void, Boolean> {
        ProgressDialog ringProgressDialog;
        Activity activity;

        public GetDataAsyncPersonal(Activity activity)
        {
            this.activity = activity;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            ringProgressDialog = ProgressDialog.show(activity, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
            ringProgressDialog.setCancelable(false);
        }


        @Override
        protected Boolean doInBackground(String... url) {
            try{
                try {
                    DefaultHttpClient httpclient = new DefaultHttpClient();
                    HttpGet httppost = new HttpGet(url[0]);
                    HttpResponse response = null;
                    response = httpclient.execute(httppost);
                    HttpEntity ht = response.getEntity();
                    BufferedHttpEntity buf = new BufferedHttpEntity(ht);
                    InputStream is = buf.getContent();
                    BufferedReader br = new BufferedReader(new InputStreamReader(is));
                    String inputLine = null;
                    try {
                        inputLine = br.readLine();
                        boolean dummyLink = false;
                        int j = 0;
                        int line = 0;
                        while ((inputLine = br.readLine()) != null){
                            String st = inputLine.toString();
                            line++;
                            if(st.startsWith("http") || st.startsWith("rtmp") || st.startsWith("rtsp") || st.startsWith("mmsh")){
                                if(dummyLink) {
                                    dummyLink = false;
                                }else{
                                    j++;
                                    channelLinkPersonal.add(st);
                                }
                            }
                            String dump = st;
                            for (int i=0; i<st.length()-1; i++){
                                if(st.charAt(i)==','){
                                    String afterComma = dump.replaceAll(".*,", "").trim();
                                    if(!Character.isLetterOrDigit(afterComma.charAt(0))){
                                        Pattern pattern = Pattern.compile("[^a-z A-Z]");
                                        Matcher matcher = pattern.matcher(afterComma);
                                        categoryNamePersonal.add(matcher.replaceAll(""));
                                        dummyLink = true;
                                        if(line > 1) {
                                            categorySizePersonal.add(j);
                                        }
                                    }else if(Character.isLetterOrDigit(afterComma.charAt(0))){
                                        channelNamePersonal.add(afterComma);
                                    }
                                }
                            }
                        }
                        categorySizePersonal.add(j);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }catch(Exception e) {
                Log.e(TAG, "Data Async: " + e);
            }
            return true;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            super.onPostExecute(success);
            ringProgressDialog.dismiss();
        }
    }

    /**
     * This class extends AsyncTask and implements code for getting playlist (.m3u format)
     */
    private class DownloadM3UList extends AsyncTask<String, Integer, String> {

        private Context context;
        private PowerManager.WakeLock mWakeLock;

        public DownloadM3UList(Context context) {
            this.context = context;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // take CPU lock to prevent CPU from going off if the user
            // presses the power button during download
            PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                    getClass().getName());
            mWakeLock.acquire();
            mProgressDialog.show();
        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            super.onProgressUpdate(progress);
            // if we get here, length is known, now set indeterminate to false
            mProgressDialog.setIndeterminate(false);
            mProgressDialog.setMax(100);
            mProgressDialog.setProgress(progress[0]);
        }

        @Override
        protected String doInBackground(String... sUrl) {
            InputStream input = null;
            OutputStream output = null;
            HttpURLConnection connection = null;
            try {
                URL url = new URL(sUrl[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.connect();

                // expect HTTP 200 OK, so we don't mistakenly save error report
                // instead of the file
                if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                    return "Server returned HTTP " + connection.getResponseCode()
                            + " " + connection.getResponseMessage();
                }

                // this will be useful to display download percentage
                // might be -1: server did not report the length
                int fileLength = connection.getContentLength();

                // download the file
                input = connection.getInputStream();
                File folder = new File(Environment.getExternalStorageDirectory() + "/ListIPTV");
                boolean success = true;
                if (!folder.exists()) {
                    success = folder.mkdir();
                }
                if (success) {
                    output = new FileOutputStream(Environment.getExternalStorageDirectory() + "/ListIPTV/listIPTV.m3u");
                } else {
                    Log.e(TAG, "Directory not created!");
                }
                DocumentBuilderFactory dbFactory
                        = DocumentBuilderFactory.newInstance();
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                Document doc = dBuilder.parse(URL);
                doc.getDocumentElement().normalize();
                String dataString = doc.getElementsByTagName("List").item(0).getTextContent();
                /*
                byte data[] = new byte[4096];
                long total = 0;
                int count;
                while ((count = input.read(data)) != -1) {
                    // allow canceling with back button
                    if (isCancelled()) {
                        input.close();
                        return null;
                    }

                    total += count;

                    // publishing the progress....
                    if (fileLength > 0) // only if total length is known
                        publishProgress((int) (total * 100 / fileLength));

                    output.write(data, 0, count);
                }
                */
                byte[] dataStringBytes = dataString.getBytes(StandardCharsets.UTF_8);
                output.write(dataStringBytes, 0, dataStringBytes.length);
                // flushing output
                output.flush();
            } catch (Exception e) {
                Log.e("DATA:", e.toString());
                return e.toString();
            } finally {
                try {
                    if (output != null)
                        output.close();
                    if (input != null)
                        input.close();
                } catch (IOException ignored) {
                }

                if (connection != null)
                    connection.disconnect();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            mWakeLock.release();
            mProgressDialog.dismiss();
            if (result != null) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    Snackbar.make(coordinatorLayout, getResources().getString(R.string.download_error) + " " + result, Snackbar.LENGTH_LONG).show();
                } else {
                    Toast.makeText(context, getResources().getString(R.string.download_error) + " " + result, Toast.LENGTH_LONG).show();
                }
            }
            else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    Snackbar.make(coordinatorLayout, getResources().getString(R.string.download_success), Snackbar.LENGTH_LONG)
                            .setAction(getResources().getString(R.string.snackbar_open), new View.OnClickListener() {
                                @Override
                                public void onClick(View view) {
                                    Uri selectedUri = Uri.parse(Environment.getExternalStorageDirectory() + "/ListIPTV");
                                    Intent intent = new Intent(Intent.ACTION_VIEW);
                                    intent.setDataAndType(selectedUri, "resource/folder");

                                    if (intent.resolveActivityInfo(getPackageManager(), 0) != null)
                                    {
                                        startActivity(intent);
                                    }
                                }
                            })
                            .show();
                }else{
                    Toast.makeText(context, getResources().getString(R.string.download_success), Toast.LENGTH_LONG).show();
                }
            }
        }
    }


    /**
     * This class extends AsyncTask and get data from Shared Preferences
     */
    private class RestoreDataAsync extends AsyncTask<Void, Void, Boolean> {
        ProgressDialog ringProgressDialog;
        Activity activity;

        public RestoreDataAsync(Activity activity)
        {
            this.activity = activity;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            ringProgressDialog = ProgressDialog.show(activity, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
            ringProgressDialog.setCancelable(false);
        }


        @Override
        protected Boolean doInBackground(Void... url) {
            //Restore Data from SharedPreferences
            restorePersonalList();
            restoreFavoriteList();
            restoreListState();
            return true;
        }

        @Override
        protected void onPostExecute(Boolean success) {
            super.onPostExecute(success);
            ringProgressDialog.dismiss();
        }
    }



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //Get locale language
        if(Locale.getDefault().getDisplayLanguage().equalsIgnoreCase("English"))
        {
            //Set URL for English language
            URL = "https://raw.githubusercontent.com/michelelacorte/IPTVFree/master/English/iptvlistEnglish.xml";
        }
        if(Locale.getDefault().getDisplayLanguage().equalsIgnoreCase("Italiano"))
        {
            //Set URL for Italian language
            URL = "https://raw.githubusercontent.com/michelelacorte/IPTVFree/master/Italiano/iptvlistItalian.xml";
        }
        //Check if connection is enabled, it is necessary!
        if(Utils.isOnline(getApplicationContext())) {
            PackageManager pm = getApplicationContext().getPackageManager();
            boolean isInstalledMXPlayer = Utils.isPackageInstalled("com.mxtech.videoplayer.ad", pm);
            boolean isInstalledXMTVPlayer = Utils.isPackageInstalled("com.xmtvplayer.watch.live.streams", pm);
            //Check if MXPlayer is installed, it is necessary!
            if(!isInstalledMXPlayer && !isInstalledXMTVPlayer) {
                    Spanned alertText = null;
                    if(Locale.getDefault().getDisplayLanguage().equalsIgnoreCase("English"))
                    {
                        alertText = Html.fromHtml("Please install a media player to use IPTV Free. \n\n\nWe suggest you <a href=\"https://github.com/michelelacorte/IPTVFree/raw/master/xmtvplayer.apk\">XMTV Player</a> or <a href=\"https://play.google.com/store/apps/details?id=com.mxtech.videoplayer.ad&hl=it\">MX Player</a>");
                    }
                    if(Locale.getDefault().getDisplayLanguage().equalsIgnoreCase("Italiano"))
                    {
                        alertText = Html.fromHtml("Per favore installa un lettore multimediale per utilizzare IPTV Free. \n\n\nTi consigliamo <a href=\"https://github.com/michelelacorte/IPTVFree/raw/master/xmtvplayer.apk\">XMTV Player</a> oppure <a href=\"https://play.google.com/store/apps/details?id=com.mxtech.videoplayer.ad&hl=it\">MX Player</a>");
                    }
                    ((TextView) new AlertDialog.Builder(this, R.style.AlertDialogCustom)
                            .setTitle(getResources().getString(R.string.app_name))
                            .setMessage(alertText)
                            .setCancelable(false)
                            .setPositiveButton(getResources().getString(R.string.ok_dialog), new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    //No operation
                                }
                            })
                            .show()
                            .findViewById(android.R.id.message))
                            .setMovementMethod(LinkMovementMethod.getInstance());
            }
                if(FirstRun.isFirstLaunch(getApplicationContext())) {
                    //Show disclaimer
                    disclaimerAlertDialog();
                }

                try {
                    new GetDataAsync(this).execute(URL).get();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }


                //Request explicit permission (on android M)
                requestWriteExternalStoragePermission(this);


                //Other inizialize object
                toolbar = (Toolbar) findViewById(R.id.toolbar);
                setSupportActionBar(toolbar);
                tabLayout = (TabLayout) findViewById(R.id.tabs);
                viewPager = (ViewPager) findViewById(R.id.viewpager);
                coordinatorLayout = (CoordinatorLayout) findViewById(R.id
                        .coordinatorLayout);

                //Fab menĂ¹ initialize object
                labelAdd = (TextView)findViewById(R.id.labeAdd);
                labelDownload = (TextView)findViewById(R.id.labelDownload);
                fabMenu = (FloatingActionButton)findViewById(R.id.fabMenu);
                fabAdd = (FloatingActionButton)findViewById(R.id.fabAdd);
                fabDownload = (FloatingActionButton)findViewById(R.id.fabDownload);
                fab_open = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fab_open);
                fab_close = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.fab_close);
                rotate_forward = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.rotate_forward);
                rotate_backward = AnimationUtils.loadAnimation(getApplicationContext(),R.anim.rotate_backward);
                fabMenu.setOnClickListener(this);
                fabAdd.setOnClickListener(this);
                fabDownload.setOnClickListener(this);

                searchView = (MaterialSearchView) findViewById(R.id.search_view);
                channelNameArray = channelName.toArray(new String[channelName.size()]);
                searchView.setSuggestions(channelNameArray);
                searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
                    @Override
                    public boolean onQueryTextSubmit(String query) {
                        int position = 0;
                        for(int i = 0; i < channelName.size(); i++)
                        {
                            if(channelName.get(i).equalsIgnoreCase(query))
                            {
                                position = i;
                            }
                        }
                        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(channelLink.get(position)));
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivity(intent);
                        return true;
                    }

                    @Override
                    public boolean onQueryTextChange(String newText) {
                        //Do some magic
                        return false;
                    }
                });

                if(!FirstRun.isFirstLaunch(getApplicationContext())) {
                    //Restore Data from SharedPreferences asynchronous
                    new RestoreDataAsync(this).execute();
                }

                NavigationView navigationView = (NavigationView) findViewById(R.id.navigation_view);
                navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(MenuItem menuItem) {
                        switch (menuItem.getItemId()) {
                            case R.id.About:
                                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this, R.style.AlertDialogCustom);
                                builder.setTitle(getResources().getString(R.string.app_name))
                                        .setMessage(R.string.dialog_message)
                                        .setCancelable(false)
                                        .setNegativeButton(getResources().getString(R.string.ok_dialog), new DialogInterface.OnClickListener() {
                                            public void onClick(DialogInterface dialog, int id) {
                                                dialog.dismiss();
                                            }
                                        });

                                AlertDialog about = builder.create();
                                about.show();
                                ((TextView) about.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
                                drawerLayout.closeDrawers();
                                break;
                            case R.id.Donate:
                                AlertDialog.Builder donate = new AlertDialog.Builder(MainActivity.this, R.style.AlertDialogCustom);
                                donate.setTitle(getResources().getString(R.string.donate))
                                        .setMessage(R.string.donate_message)
                                        .setCancelable(false)
                                        .setNegativeButton(getResources().getString(R.string.ok_dialog), new DialogInterface.OnClickListener() {
                                            public void onClick(DialogInterface dialog, int id) {
                                                dialog.dismiss();
                                            }
                                        });

                                AlertDialog donation = donate.create();
                                donation.show();
                                ((TextView) donation.findViewById(android.R.id.message)).setMovementMethod(LinkMovementMethod.getInstance());
                                drawerLayout.closeDrawers();
                                break;
                            case R.id.Share:
                                Intent share = new Intent(Intent.ACTION_SEND);
                                share.setType("text/plain");
                                share.putExtra(Intent.EXTRA_TEXT, getResources().getString(R.string.share_message));
                                startActivity(Intent.createChooser(share, getResources().getString(R.string.app_name)));
                                drawerLayout.closeDrawers();
                                break;
                            case R.id.italian:
                                MainActivity.this.setTitle(getResources().getString(R.string.italian));
                                item.setVisible(true);
                                ringProgressDialog = ProgressDialog.show(MainActivity.this, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
                                ringProgressDialog.setCancelable(false);
                                Utils.clearIfNotEmpty(categoryName, categorySize, channelName, channelLink);
                                URL = "https://raw.githubusercontent.com/michelelacorte/IPTVFree/master/Italiano/iptvlistItalian.xml";
                                try {
                                    new GetDataAsync(MainActivity.this).execute(URL).get();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                } catch (ExecutionException e) {
                                    e.printStackTrace();
                                }
                                myrunnable = new Runnable() {
                                    public void run() {
                                        setupViewPager(viewPager);
                                        tabLayout.setupWithViewPager(viewPager);
                                        ringProgressDialog.dismiss();
                                    }
                                };
                                handler.postDelayed(myrunnable, 1000);
                                channelNameArray = channelName.toArray(new String[channelName.size()]);
                                searchView.setSuggestions(channelNameArray);
                                drawerLayout.closeDrawers();
                                break;
                            case R.id.english:
                                MainActivity.this.setTitle(getResources().getString(R.string.english));
                                item.setVisible(true);
                                ringProgressDialog = ProgressDialog.show(MainActivity.this, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
                                ringProgressDialog.setCancelable(false);
                                Utils.clearIfNotEmpty(categoryName, categorySize, channelName, channelLink);
                                URL = "https://raw.githubusercontent.com/michelelacorte/IPTVFree/master/English/iptvlistEnglish.xml";
                                try {
                                    new GetDataAsync(MainActivity.this).execute(URL).get();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                } catch (ExecutionException e) {
                                    e.printStackTrace();
                                }
                                myrunnable = new Runnable() {
                                    public void run() {
                                        setupViewPager(viewPager);
                                        tabLayout.setupWithViewPager(viewPager);
                                        ringProgressDialog.dismiss();
                                    }
                                    };
                                handler.postDelayed(myrunnable, 1000);
                                channelNameArray = channelName.toArray(new String[channelName.size()]);
                                searchView.setSuggestions(channelNameArray);
                                drawerLayout.closeDrawers();
                                break;
                            case R.id.mixed:
                                MainActivity.this.setTitle(getResources().getString(R.string.mixed));
                                item.setVisible(true);
                                ringProgressDialog = ProgressDialog.show(MainActivity.this, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
                                ringProgressDialog.setCancelable(false);
                                Utils.clearIfNotEmpty(categoryName, categorySize, channelName, channelLink);
                                URL = "https://raw.githubusercontent.com/michelelacorte/IPTVFree/master/Mixed/iptvlistMixed.xml";
                                try {
                                    new GetDataAsync(MainActivity.this).execute(URL).get();
                                } catch (InterruptedException e) {
                                    e.printStackTrace();
                                } catch (ExecutionException e) {
                                    e.printStackTrace();
                                }
                                myrunnable = new Runnable() {
                                    public void run() {
                                        setupViewPager(viewPager);
                                        tabLayout.setupWithViewPager(viewPager);
                                        ringProgressDialog.dismiss();
                                    }
                                };
                                handler.postDelayed(myrunnable, 1000);
                                channelNameArray = channelName.toArray(new String[channelName.size()]);
                                searchView.setSuggestions(channelNameArray);
                                drawerLayout.closeDrawers();
                                break;
                            case R.id.favorite:
                                if(favoriteLink != null && favoriteName != null
                                        && favoriteLink.size() > 0 && favoriteName.size() > 0) {
                                    MainActivity.this.setTitle(getResources().getString(R.string.favorite));
                                    item.setVisible(false);
                                    ringProgressDialog = ProgressDialog.show(MainActivity.this, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
                                    ringProgressDialog.setCancelable(false);
                                    isFavorite = true;
                                    myrunnable = new Runnable() {
                                        public void run() {
                                            setupViewPagerFavorite(viewPager);
                                            tabLayout.setupWithViewPager(viewPager);
                                            ringProgressDialog.dismiss();
                                        }
                                    };
                                    handler.postDelayed(myrunnable, 1000);
                                }else{
                                    AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this, R.style.AlertDialogCustom);
                                    dialog.setTitle(getResources().getString(R.string.dialog_loader_list_favorite));
                                    dialog.setMessage(getResources().getString(R.string.dialog_loader_list_favorite_message));
                                    dialog.setCancelable(true);
                                    dialog.setNegativeButton(getResources().getString(R.string.dialog_loader_cancel), new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            dialog.cancel();
                                        }
                                    });
                                    dialog.create();
                                    dialog.show();
                                }
                                drawerLayout.closeDrawers();
                                break;
                            case R.id.Bug:
                                BugReport.reportBug(MainActivity.this);
                                drawerLayout.closeDrawers();
                                break;
                            case R.id.mylist:
                                if(isMyListLoadedFromPath) {
                                    MainActivity.this.setTitle(getResources().getString(R.string.mylist));
                                    item.setVisible(false);
                                    ringProgressDialog = ProgressDialog.show(MainActivity.this, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
                                    ringProgressDialog.setCancelable(false);
                                    myrunnable = new Runnable() {
                                        public void run() {
                                            setupViewPagerPersonal(viewPager);
                                            tabLayout.setupWithViewPager(viewPager);
                                            ringProgressDialog.dismiss();
                                        }
                                    };
                                    handler.postDelayed(myrunnable, 1000);
                                    drawerLayout.closeDrawers();
                                }else if(isMyListLoadedFromURL) {
                                    MainActivity.this.setTitle(getResources().getString(R.string.mylist));
                                    item.setVisible(false);
                                    ringProgressDialog = ProgressDialog.show(MainActivity.this, getResources().getString(R.string.please_wait), getResources().getString(R.string.getting_data), true);
                                    ringProgressDialog.setCancelable(false);
                                    Utils.clearIfNotEmpty(categoryNamePersonal, categorySizePersonal, channelNamePersonal, channelLinkPersonal);
                                    URL = Utils.getLoadedFromURLString();
                                    if(FirstRun.isFirstLaunch(getApplicationContext()))
                                    {
                                        preferencesIPTV.savePreferencesURL(getApplicationContext(), "PersonalURL", URL);
                                    }else if(URL == null)
                                    {
                                        URL = preferencesIPTV.loadPreferencesURL(getApplicationContext(), "PersonalURL");
                                    }
                                    preferencesIPTV.savePreferencesURL(getApplicationContext(), "PersonalURL", URL);
                                    try {
                                        new GetDataAsyncPersonal(MainActivity.this).execute(URL).get();
                                    } catch (InterruptedException e) {
                                        e.printStackTrace();
                                    } catch (ExecutionException e) {
                                        e.printStackTrace();
                                    }
                                    myrunnable = new Runnable() {
                                        public void run() {
                                            setupViewPagerPersonal(viewPager);
                                            tabLayout.setupWithViewPager(viewPager);
                                            ringProgressDialog.dismiss();
                                        }
                                    };
                                    handler.postDelayed(myrunnable, 10000);
                                    drawerLayout.closeDrawers();
                                }else{
                                    AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.this, R.style.AlertDialogCustom);
                                    dialog.setTitle(getResources().getString(R.string.dialog_loader_list_title));
                                    dialog.setMessage(getResources().getString(R.string.dialog_loader_list_message));
                                    dialog.setCancelable(true);
                                    dialog.setNegativeButton(getResources().getString(R.string.dialog_loader_cancel), new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            dialog.cancel();
                                        }
                                    });
                                    dialog.create();
                                    dialog.show();
                                }
                                drawerLayout.closeDrawers();
                                break;
                            default:
                                break;
                        }
                        return false;
                    }
                });

                drawerLayout = (DrawerLayout) findViewById(R.id.DrawerLayout);
                mDrawerToggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close) {
                    @Override
                    public void onDrawerClosed(View drawerView) {
                        super.onDrawerClosed(drawerView);
                    }

                    @Override
                    public void onDrawerOpened(View drawerView) {
                        super.onDrawerOpened(drawerView);
                    }
                };
                drawerLayout.post(new Runnable() {
                    @Override
                    public void run() {
                        mDrawerToggle.syncState();
                    }
                });
                drawerLayout.setDrawerListener(mDrawerToggle);
                mDrawerToggle.syncState();
                //Set-up Tab
                setupViewPager(viewPager);
                tabLayout.setupWithViewPager(viewPager);

                Utils.tutorialView(this, "IPTVFreeIntroView", toolbar, fabMenu, tabLayout, viewPager, searchView);
        }else{
            AlertDialog.Builder builder =
                    new AlertDialog.Builder(this, R.style.AlertDialogCustom);
            builder.setTitle(getResources().getString(R.string.app_name));
            builder.setCancelable(false);
            builder.setMessage(getResources().getString(R.string.connection));
            builder.setPositiveButton(getResources().getString(R.string.ok_dialog), new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    finish();
                }
            });
            builder.show();
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == MaterialSearchView.REQUEST_VOICE && resultCode == RESULT_OK) {
            ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
            if (matches != null && matches.size() > 0) {
                String searchWrd = matches.get(0);
                if (!TextUtils.isEmpty(searchWrd)) {
                    searchView.setQuery(searchWrd, false);
                }
            }

            return;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_search, menu);

        item = menu.findItem(R.id.action_search);
        searchView.setMenuItem(item);

        return true;
    }

    /**
     * Hanlde request permission result
     * @param requestCode int
     * @param permissions String[]
     * @param grantResults int[]
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        switch ( requestCode ) {
            case REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSIONS: {
                for( int i = 0; i < permissions.length; i++ ) {
                    if( grantResults[i] == PackageManager.PERMISSION_GRANTED ) {
                        Log.d( "Permissions", "Permission Granted: " + permissions[i] );
                    } else if( grantResults[i] == PackageManager.PERMISSION_DENIED ) {
                        Log.d( "Permissions", "Permission Denied: " + permissions[i] );
                    }
                }
            }
            break;
            default: {
                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            }
        }
    }

    /**
     * On click interface implemented
     * @param v View
     */
    @Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id){
            case R.id.fabMenu:
                animateFAB();
                break;
            case R.id.fabAdd:
                Utils.addFromURLOrFolder(MainActivity.this);
                closeFAB();
                break;
            case R.id.fabDownload:
                closeFAB();
                mProgressDialog = new ProgressDialog(MainActivity.this);
                mProgressDialog.setMessage(getResources().getString(R.string.download_message));
                mProgressDialog.setIndeterminate(true);
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                mProgressDialog.setCancelable(true);
                final DownloadM3UList downloadTask = new DownloadM3UList(MainActivity.this);
                downloadTask.execute(URL);

                mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialog) {
                        downloadTask.cancel(true);
                    }
                });
                break;
        }
    }

    /**
     * On stop application
     */
    @Override
    public void onStop()
    {
        super.onStop();
        savePersonalList();
        saveFavoriteList();
        saveListState();
    }

    /**
     * On destroy application
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        savePersonalList();
        saveFavoriteList();
        saveListState();
    }

    /**
     * On pause application
     */
    @Override
    public void onPause()
    {
        super.onPause();
        savePersonalList();
        saveFavoriteList();
        saveListState();
    }

    /**
     * Series of option for close FAB
     */
    private void closeFAB()
    {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            labelAdd.startAnimation(fab_close);
            labelDownload.startAnimation(fab_close);
        }
        fabMenu.startAnimation(rotate_backward);
        fabAdd.startAnimation(fab_close);
        fabDownload.startAnimation(fab_close);
        fabAdd.setClickable(false);
        fabDownload.setClickable(false);
        isFabOpen = false;
    }

    /**
     * Series of option for open FAB
     */
    private void openFAB()
    {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            labelAdd.startAnimation(fab_open);
            labelDownload.startAnimation(fab_open);
        }
        fabMenu.startAnimation(rotate_forward);
        fabAdd.startAnimation(fab_open);
        fabDownload.startAnimation(fab_open);
        fabAdd.setClickable(true);
        fabDownload.setClickable(true);
        isFabOpen = true;
    }

    /**
     * Animation of Floating Action Button
     */
    public void animateFAB(){
        if(isFabOpen){
            closeFAB();
        } else {
            openFAB();
        }
    }

    /**
     * Set up view pager of other category
     * @param viewPager ViewPager
     */
    private void setupViewPager(final ViewPager viewPager) {
        adapter = new ViewPagerAdapter(getSupportFragmentManager());
        CATEGORY = 0;
        CATEGORY_INDEX = 0;
        DEFAULT = true;
        if(Utils.isOnline(getApplicationContext())) {
            for (int i = 0; i < categoryName.size(); i++) {
                try {
                    if (MainActivity.categorySize.get(MainActivity.CATEGORY_INDEX) != null) {
                        ArrayList<String> channels = new ArrayList<String>(channelName.subList(CATEGORY, categorySize.get(CATEGORY_INDEX)));
                        ArrayList<String> links = new ArrayList<String>(channelLink.subList(CATEGORY, categorySize.get(CATEGORY_INDEX)));
                        CATEGORY = categorySize.get(CATEGORY_INDEX);
                        CATEGORY_INDEX++;
                        adapter.addFragment(FragmentIPTV.newInstance(channels, links), categoryName.get(i));
                        DEFAULT = false;
                    }
                } catch (Exception e) {
                        ArrayList<String> channels = new ArrayList<String>(channelName.subList(CATEGORY, channelName.size()));
                        ArrayList<String> links = new ArrayList<String>(channelLink.subList(CATEGORY, channelLink.size()));
                        adapter.addFragment(FragmentIPTV.newInstance(channels, links), categoryName.get(i));

                }
            }
            viewPager.setAdapter(adapter);
        }

    }

    /**
     * Setup View pager with personal data
     * @param viewPager ViewPager
     */
    private void setupViewPagerPersonal(final ViewPager viewPager) {
        adapter = new ViewPagerAdapter(getSupportFragmentManager());
        CATEGORY = 0;
        CATEGORY_INDEX = 0;
        DEFAULT = true;
        if(Utils.isOnline(getApplicationContext())) {
            for (int i = 0; i < categoryNamePersonal.size(); i++) {
                try {
                    if (MainActivity.categorySizePersonal.get(MainActivity.CATEGORY_INDEX) != null) {
                        ArrayList<String> channels = new ArrayList<String>(channelNamePersonal.subList(CATEGORY, categorySizePersonal.get(CATEGORY_INDEX)));
                        ArrayList<String> links = new ArrayList<String>(channelLinkPersonal.subList(CATEGORY, categorySizePersonal.get(CATEGORY_INDEX)));
                        CATEGORY = categorySizePersonal.get(CATEGORY_INDEX);
                        CATEGORY_INDEX++;
                        adapter.addFragment(FragmentIPTV.newInstance(channels, links), categoryNamePersonal.get(i));
                        DEFAULT = false;
                    }
                } catch (Exception e) {
                    ArrayList<String> channels = new ArrayList<String>(channelNamePersonal.subList(CATEGORY, channelNamePersonal.size()));
                    ArrayList<String> links = new ArrayList<String>(channelLinkPersonal.subList(CATEGORY, channelLinkPersonal.size()));
                    adapter.addFragment(FragmentIPTV.newInstance(channels, links), categoryNamePersonal.get(i));

                }
            }
            viewPager.setAdapter(adapter);
        }

    }

    /**
     * Set up view pager of Favorite category
     * @param viewPager ViewPager
     */
    private void setupViewPagerFavorite(final ViewPager viewPager) {
        adapter = new ViewPagerAdapter(getSupportFragmentManager());
        if(Utils.isOnline(getApplicationContext())) {
            if(isFavorite) {
                adapter.addFragment(FragmentIPTVFavorite.newInstance(favoriteName, favoriteLink), getResources().getString(R.string.favorite));
            }
            viewPager.setAdapter(adapter);
        }

    }


    /**
     * Handle file listener response
     * @param activity Activity
     * @return
     */
    public static OnHandleFileListener onHandleFileListener(final Activity activity) {
        return new OnHandleFileListener() {
            @Override
            public void handleFile(final String filePath) {
                try{
                    try {
                        Utils.clearIfNotEmpty(categoryNamePersonal, categorySizePersonal, channelNamePersonal, channelLinkPersonal);
                        File file = new File(filePath);
                        BufferedReader br = new BufferedReader(new FileReader(file));
                        String inputLine = null;
                        try {
                            inputLine = br.readLine();
                            boolean dummyLink = false;
                            int j = 0;
                            int line = 0;
                            while ((inputLine = br.readLine()) != null){
                                String st = inputLine.toString();
                                line++;
                                if(st.equalsIgnoreCase("#EXTM3U"))
                                {
                                    //Not relevant line, decrease.
                                    line--;
                                }
                                if(st.startsWith("http") || st.startsWith("rtmp") || st.startsWith("rtsp") || st.startsWith("mmsh")){
                                    if(dummyLink) {
                                        dummyLink = false;
                                    }else{
                                        j++;
                                        channelLinkPersonal.add(st);
                                    }
                                }
                                String dump = st;
                                for (int i=0; i<st.length()-1; i++){
                                    if(st.charAt(i)==','){
                                        String afterComma = dump.replaceAll(".*,", "").trim();
                                        if(!Character.isLetterOrDigit(afterComma.charAt(0))){
                                            Pattern pattern = Pattern.compile("[^a-z A-Z]");
                                            Matcher matcher = pattern.matcher(afterComma);
                                            categoryNamePersonal.add(matcher.replaceAll(""));
                                            dummyLink = true;
                                            if(line > 1) {
                                                categorySizePersonal.add(j);
                                            }
                                        }else if(Character.isLetterOrDigit(afterComma.charAt(0))){
                                            channelNamePersonal.add(afterComma);
                                        }
                                    }
                                }
                            }
                            categorySizePersonal.add(j);
                            isMyListLoadedFromPath = true;
                            isMyListLoadedFromURL = false;
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                }catch(Exception e) {
                    Log.e(TAG, "Data Async: " + e);
                }
                Toast.makeText(activity, activity.getResources().getString(R.string.dialog_loader_load) + ": " + filePath, Toast.LENGTH_LONG).show();
            }
        };
    }

    /**
     * Request permission on android M
     * @param activity Activity
     */
    public void requestWriteExternalStoragePermission(Activity activity)
    {
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int hasWriteExternalStoragePermission = activity.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            List<String> permissions = new ArrayList<String>();
            if (hasWriteExternalStoragePermission != PackageManager.PERMISSION_GRANTED) {
                permissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
            }
            if (!permissions.isEmpty()) {
                activity.requestPermissions(permissions.toArray(new String[permissions.size()]), REQUEST_WRITE_EXTERNAL_STORAGE_PERMISSIONS);
            }
        }
    }

    /**
     * Save personal list on Shared Preferences
     */
    private void savePersonalList()
    {
        preferencesIPTV.savePreferencesData(getApplicationContext(),  "channelNamePersonal", channelNamePersonal);
        preferencesIPTV.savePreferencesData(getApplicationContext(), "channelLinkPersonal", channelLinkPersonal);
        preferencesIPTV.savePreferencesData(getApplicationContext(), "categoryNamePersonal", categoryNamePersonal);
        List<String> convertedCategorySizePersonal = new ArrayList<String>(categorySizePersonal.size());
        for (Integer myInt : categorySizePersonal) {
            convertedCategorySizePersonal.add(String.valueOf(myInt));
        }
        preferencesIPTV.savePreferencesData(getApplicationContext(), "categorySizePersonal", convertedCategorySizePersonal);
    }

    /**
     * Restore personal list from Shared Preferences
     */
    private void restorePersonalList()
    {
        try {
            channelLinkPersonal = preferencesIPTV.loadPreferencesData(getApplicationContext(), "channelLinkPersonal");
            channelNamePersonal = preferencesIPTV.loadPreferencesData(getApplicationContext(), "channelNamePersonal");
            categoryNamePersonal = preferencesIPTV.loadPreferencesData(getApplicationContext(), "categoryNamePersonal");
            List<String> convertedCategorySizePersonal = preferencesIPTV.loadPreferencesData(getApplicationContext(), "categorySizePersonal");
            for (String toConvert : convertedCategorySizePersonal) {
                categorySizePersonal.add(Integer.valueOf(toConvert));
            }
            Collections.sort(categorySizePersonal);
        }catch(Exception e)
        {
            Log.e(TAG, "Some list are empty! \n" + e);
        }
    }

    /**
     * Save favorite list on Shared Preferences
     */
    private void saveFavoriteList()
    {
        preferencesIPTV.savePreferencesData(getApplicationContext(), "favoriteName", favoriteName);
        preferencesIPTV.savePreferencesData(getApplicationContext(), "favoriteLink", favoriteLink);
    }

    /**
     * Restore favorite list from Shared Preferences
     */
    private void restoreFavoriteList()
    {
        try {
            favoriteName = preferencesIPTV.loadPreferencesData(getApplicationContext(), "favoriteName");
            favoriteLink = preferencesIPTV.loadPreferencesData(getApplicationContext(), "favoriteLink");
        }catch(Exception e){
            Log.e(TAG, "Some list are empty! \n" + e);
        }
    }

    /**
     * Save list state on Shared Preferences
     */
    private void saveListState()
    {
        state = new ArrayList<>();
        state.add(String.valueOf(isMyListLoadedFromPath));
        state.add(String.valueOf(isMyListLoadedFromURL));
        preferencesIPTV.savePreferencesData(getApplicationContext(), "stateList", state);
    }

    /**
     * Restore list state on Shared Preferences
     */
    private void restoreListState()
    {
        try {
            state = preferencesIPTV.loadPreferencesData(getApplicationContext(), "stateList");
            isMyListLoadedFromPath = Boolean.valueOf(state.get(0));
            isMyListLoadedFromURL = Boolean.valueOf(state.get(1));
        }catch(Exception e){
            Log.e(TAG, "Some list are empty! \n" + e);
        }
    }

    private void disclaimerAlertDialog()
    {
        AlertDialog.Builder builder =
                new AlertDialog.Builder(this, R.style.AlertDialogCustom);
        builder.setTitle(getResources().getString(R.string.app_name));
        builder.setCancelable(false);
        builder.setMessage(getResources().getString(R.string.disclaimer_dialog_message));
        builder.setNegativeButton(getResources().getString(R.string.disclaimer_dialog_no), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                finish();
            }
        });
        builder.setNegativeButton(getResources().getString(R.string.disclaimer_dialog_yes), new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
               //no operation
            }
        });
        builder.show();
    }
}