package com.cygnusa.hyperm;

import android.annotation.SuppressLint;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.StrictMode;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
import com.github.barteksc.pdfviewer.listener.OnPageErrorListener;
import com.github.barteksc.pdfviewer.scroll.DefaultScrollHandle;
import com.github.barteksc.pdfviewer.util.FitPolicy;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
import com.cygnusa.hyperm.util.ApiService;
import com.cygnusa.hyperm.util.GlobalData;
import com.cygnusa.hyperm.util.MainApplication;
import com.cygnusa.hyperm.util.MyCallback;
import com.cygnusa.hyperm.util.StorePreference;
import com.cygnusa.hyperm.util.UtilService;
import com.cygnusa.hyperm.wrappers.CommonResponse;
import com.cygnusa.hyperm.wrappers.ContentFile;
import com.cygnusa.hyperm.wrappers.ErrorResponse;
import com.cygnusa.hyperm.wrappers.HitCountModel;
import com.cygnusa.hyperm.wrappers.MyContent;
import com.cygnusa.hyperm.wrappers.MyTopic;
import com.cygnusa.hyperm.wrappers.TrainingCategory;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Objects;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;


public class PdfViewActivity extends AppCompatActivity implements OnPageChangeListener, OnPageErrorListener, OnLoadCompleteListener {
    TextView title, contentTitle, mTextLanguageSelection;
    public static MyContent CONTENT = new MyContent();
    public static MyTopic TOPIC = new MyTopic();
    public static TrainingCategory TRAINING_ID = new TrainingCategory();
    //  public static String TRAINING_ID="";
    ImageView mImageLangSelection;
    ProgressBar progressBar;
    PDFView pdfView;
    ApiService restService;
    private AlertDialog.Builder builder;
    private ContentFile SELECTED_CONTENT = new ContentFile();
    String type;
    public static boolean isOffline = false;
    Handler handler = new Handler();
    public static final String HASH_ALGORITHM = "SHA-256";
    public String encryptKey = "Hyperm";
    public File decryptFile = null;
    private StorePreference storePreference;
    public static String tempfilename = "temp";
    String fromTime, toTime, finalTime;
    Calendar c;
    SimpleDateFormat df;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_pdf_view);
        setupWindowAnimations();
        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            type = extras.getString("type");
        }
        restService = ((MainApplication) getApplication()).getClient();
        title = findViewById(R.id.title);
        File f = new File(Objects.requireNonNull(getApplicationContext()).getExternalFilesDir(null), ".HYPERM");
        if (!f.exists()) {
            f.mkdirs();
        }

        File f1 = new File(Objects.requireNonNull(getApplicationContext()).getExternalFilesDir(null) + "/" + ".HYPERM", "PDF");
        if (!f1.exists()) {
            f1.mkdirs();
        }
        storePreference = new StorePreference(this);


        getCurrentTime();

        contentTitle = findViewById(R.id.contentTitle);
        mTextLanguageSelection = findViewById(R.id.textLanguage);
        mImageLangSelection = findViewById(R.id.imgLanguage);
        progressBar = findViewById(R.id.progressBar);
        pdfView = findViewById(R.id.pdfView);
        progressBar.setVisibility(View.VISIBLE);
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

        mTextLanguageSelection.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showLanguageSelectionList();
            }
        });
        mImageLangSelection.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                showLanguageSelectionList();
            }
        });


        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        toolbar.setContentInsetStartWithNavigation(0);
        toolbar.setTitle("");
        getSupportActionBar().setTitle("");
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setDisplayShowHomeEnabled(true);

        @SuppressLint("PrivateResource")
        Drawable backArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_material);
        backArrow.setColorFilter(getResources().getColor(R.color.btn_bg_color), PorterDuff.Mode.SRC_ATOP);
        getSupportActionBar().setHomeAsUpIndicator(backArrow);

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                LoadContentFile(getContentFile());
            }
        }, 1000);

    }

    private void getCurrentTime() {
        c = Calendar.getInstance();
        System.out.println("fromTime " + c.getTime());

        df = new SimpleDateFormat("HH:mm:ss");
        fromTime = df.format(c.getTime());
        Log.e("fromTime", fromTime);
    }

    private void sendHitCountToServer() {
        restService.sendAllHitCount(buildConfigData()).enqueue(new Callback<CommonResponse>() {
            @Override
            public void onResponse(Call<CommonResponse> call, Response<CommonResponse> response) {
                if (response.body() != null) {
                    Log.e("responeHit", response.body().getMessage());
                } else {
                    Log.e("responeHit", response.body().getMessage());
                }
            }

            @Override
            public void onFailure(Call<CommonResponse> call, Throwable t) {
                if (t.getMessage() != null) {
                    Log.e("responeHit", t.getMessage());
                }
            }
        });
    }

    private HitCountModel buildConfigData() {
        HitCountModel hitCountModel = new HitCountModel();
        hitCountModel.setPage("Learning");
        hitCountModel.setAssettopicid(Integer.valueOf(CONTENT.getAssettopicid()));
        hitCountModel.setContentid(Integer.valueOf(CONTENT.getContentid()));
        hitCountModel.setViewtime(finalTime);
        return hitCountModel;
    }

    public void decrypt(String pathstr, String filetype, Runnable runnable) throws IOException, NoSuchAlgorithmException,
            NoSuchPaddingException, InvalidKeyException {
        FileInputStream fis = new FileInputStream(pathstr);
        File outputDir = this.getCacheDir(); // context being the Activity pointer
        String format = ".pdf";
        if (filetype.equalsIgnoreCase("pdf")) {
            format = ".pdf";
        } else if (filetype.equalsIgnoreCase("mp4")) {
            format = ".mp4";
        }
        decryptFile = File.createTempFile(tempfilename, format, this.getCacheDir());
        FileOutputStream fos = new FileOutputStream(decryptFile);
        SecretKeySpec sks = generateKey(encryptKey);
        Cipher cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, sks);
        CipherInputStream cis = new CipherInputStream(fis, cipher);
        int b;
        byte[] d = new byte[1024];
        while ((b = cis.read(d)) != -1) {
            fos.write(d, 0, b);
        }

        fos.flush();
        fos.close();
        cis.close();
        runnable.run();
    }


    private ArrayList<String> getContentFile(MyContent item) {
        if (item.getContent_files() == null) {
            return null;
        }
        ArrayList<String> Language = new ArrayList<>();
        for (ContentFile file : item.getContent_files()) {
            Language.add(file.getLanguage_title());
        }
        return Language;
    }
    private void showLanguageSelectionList() {
        final ArrayList<String> contentFile = getContentFile(CONTENT);
        builder = new AlertDialog.Builder(PdfViewActivity.this);
        builder.setTitle("SELECT LANGUAGE")
                .setItems(contentFile.toArray(new String[contentFile.size()]), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        LoadContentFile(CONTENT.getContent_files().get(i));
                        dialogInterface.dismiss();
                    }
                });
        builder.create().show();
    }
    public void LoadContentFile(final ContentFile con) {
        SELECTED_CONTENT = con;
        mTextLanguageSelection.setText(SELECTED_CONTENT.getLanguage_title());
        contentTitle.setText(CONTENT.getTitle());
        title.setText(CONTENT.getTitle());
        title.setSelected(true);
        pdfView.post(new Runnable() {
            @Override
            public void run() {
                File file = new File(Objects.requireNonNull(getApplicationContext()).getExternalFilesDir(null)
                        + "/" + ".HYPERM", "PDF/" + CONTENT.getContentid() + "_" + CONTENT.getVersion() + "_" + SELECTED_CONTENT.getLanguage_code() + ".pdf");
                if (file.exists()) {
                    saveTopicData();
                    try {
                        decrypt(file.toString(), "pdf", new Runnable() {
                            @Override
                            public void run() {
                                pdfView.fromFile(decryptFile)
                                        .onPageChange(PdfViewActivity.this)
                                        .enableAnnotationRendering(true)
                                        .onLoad(PdfViewActivity.this)
                                        .scrollHandle(new DefaultScrollHandle(PdfViewActivity.this))
                                        .spacing(10)
                                        .onPageError(PdfViewActivity.this)
                                        .pageFitPolicy(FitPolicy.WIDTH)
                                        .load();
                            }
                        });

                    } catch (Exception e) {
                        e.printStackTrace();
                        progressBar.setVisibility(View.GONE);
                    }
                } else {
                    downloadPDF(con);
                }
            }
        });

    }

    public void saveTopicData() {
        Cursor cursor = GlobalData.sdb.rawQuery("select * from topic_content where" + " category_id='"
                + TRAINING_ID.getCateid() + "' and topic_id='" + TOPIC.getAssettopicid() + "' and content_id='" + CONTENT.getContentid() + "'", null);
        if (cursor.getCount() == 0) {

            Gson gson = new Gson();
            JsonElement jsonElement = gson.toJsonTree(
                    CONTENT, new TypeToken<MyContent>() {
                    }.getType());
            ContentValues values = new ContentValues();
            values.put("topic_content", jsonElement.toString());
            values.put("category_id", TRAINING_ID.getCateid());
            values.put("topic_id", TOPIC.getAssettopicid());
            values.put("content_id", CONTENT.getContentid());
            GlobalData.sdb.insert("topic_content", null, values);
        }
        cursor = GlobalData.sdb.rawQuery("select * from topic where" + " category_id='"
                + TRAINING_ID.getCateid()
                + "' and topic_id='" + TOPIC.getAssettopicid() + "'", null);
        if (cursor.getCount() == 0) {
            Gson gson1 = new Gson();
            JsonElement jsonElement1 = gson1.toJsonTree(
                    TOPIC, new TypeToken<MyTopic>() {
                    }.getType());
            ContentValues values = new ContentValues();
            values.put("topic", jsonElement1.toString());
            values.put("category_id", TRAINING_ID.getCateid());
            values.put("topic_id", TOPIC.getAssettopicid());
            GlobalData.sdb.insert("topic", null, values);
        }
//        else {
//            GlobalData.showToast(getBaseContext(), "Please check your internet connection", Toast.LENGTH_SHORT).show();
//        }
    }

    public ContentFile getContentFile() {
        if (CONTENT.getContent_files() == null) {
            return null;
        }
        String language = this.getSharedPreferences("LANGUAGE", Context.MODE_PRIVATE).getString("DEFAULT", "en_us");

        for (ContentFile file : CONTENT.getContent_files()) {
            if (file.getLanguage_code().trim().equalsIgnoreCase(language.trim())) {
                return file;
            }
        }
        return CONTENT.getContent_files().get(0);
    }

    @SuppressLint("StaticFieldLeak")
    private void downloadPDF(final ContentFile con) {
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... voids) {
                OutputStream output = null;
                CipherOutputStream cos = null;
                InputStream input = null;
                try {
                    int count;
                    URL url = new URL(con.getFile_url());
                    URLConnection conection = url.openConnection();
                    conection.connect();
                    int lenghtOfFile = conection.getContentLength();
                    input = new BufferedInputStream(url.openStream(),
                            8192);
                    String fileName = Objects.requireNonNull(getApplicationContext()).getExternalFilesDir(null)
                            + "/" + ".HYPERM/PDF/" + CONTENT.getContentid() + "_" + CONTENT.getVersion() + "_" + SELECTED_CONTENT.getLanguage_code() + ".pdf";
                    output = new FileOutputStream(fileName);

                    SecretKeySpec sks = generateKey(encryptKey);
                    // Create cipher
                    Cipher cipher = Cipher.getInstance("AES");
                    cipher.init(Cipher.ENCRYPT_MODE, sks);
                    // Wrap the output stream
                    cos = new CipherOutputStream(output, cipher);
                    byte data[] = new byte[1024];
                    long total = 0;

                    while ((count = input.read(data)) != -1) {
                        total += count;
                        cos.write(data, 0, count);
                    }
                    cos.flush();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        cos.close();
                        input.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                return null;
            }

            @Override
            protected void onPostExecute(Void aVoid) {
                super.onPostExecute(aVoid);
                File file = new File(Objects.requireNonNull(getApplicationContext()).getExternalFilesDir(null)
                        + "/" + ".HYPERM", "PDF/" + CONTENT.getContentid() + "_" + CONTENT.getVersion() + ".pdf");
                if (file.exists()) {
                    try {
                        decrypt(file.toString(), "pdf", new Runnable() {
                            @Override
                            public void run() {
                                pdfView.fromFile(decryptFile)
                                        .onPageChange(PdfViewActivity.this)
                                        .enableAnnotationRendering(true)
                                        .onLoad(PdfViewActivity.this)
                                        .scrollHandle(new DefaultScrollHandle(PdfViewActivity.this))
                                        .spacing(10)
                                        .onPageError(PdfViewActivity.this)
                                        .pageFitPolicy(FitPolicy.WIDTH)
                                        .load();
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                        progressBar.setVisibility(View.GONE);
                    }

                } else {
                    loadPdf(con);
                }
            }
        }.execute();


    }

    public static SecretKeySpec generateKey(final String password) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        final MessageDigest digest = MessageDigest.getInstance(HASH_ALGORITHM);
        byte[] bytes = password.getBytes("UTF-8");
        digest.update(bytes, 0, bytes.length);
        byte[] key = digest.digest();
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
        return secretKeySpec;
    }

    private void loadPdf(ContentFile contentFile) {
        try {
            pdfView.fromStream(new URL(contentFile.getFile_url()).openStream())
                    .onPageChange(PdfViewActivity.this)
                    .enableAnnotationRendering(true)
                    .onLoad(PdfViewActivity.this)
                    .scrollHandle(new DefaultScrollHandle(PdfViewActivity.this))
                    .spacing(10)
                    .onPageError(PdfViewActivity.this)
                    .pageFitPolicy(FitPolicy.WIDTH)
                    .load();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private boolean writeResponseBodyToDisk(ResponseBody body) {
        try {
            File futureStudioIconFile = new File(Objects.requireNonNull(getApplicationContext()).getExternalFilesDir(null)
                    + "/" + ".HYPERM", "PDF/" + CONTENT.getContentid() + "_" + CONTENT.getVersion() + ".pdf");
            InputStream inputStream = null;
            OutputStream outputStream = null;

            try {
                byte[] fileReader = new byte[4096];
                long fileSize = body.contentLength();
                long fileSizeDownloaded = 0;
                inputStream = body.byteStream();
                outputStream = new FileOutputStream(futureStudioIconFile);

                while (true) {
                    int read = inputStream.read(fileReader);
                    if (read == -1) {
                        break;
                    }
                    outputStream.write(fileReader, 0, read);
                    fileSizeDownloaded += read;
                }
                outputStream.flush();
                return true;
            } catch (IOException e) {
                return false;
            } finally {
                if (inputStream != null) {
                    inputStream.close();
                }
                if (outputStream != null) {
                    outputStream.close();
                }
            }
        } catch (IOException e) {
            return false;
        }
    }

    private void setupWindowAnimations() {
        this.overridePendingTransition(R.anim.animation_enter,
                R.anim.animation_leave);
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            finish();
            this.overridePendingTransition(R.anim.animation_f_enter,
                    R.anim.animation_f_leave);
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        getToTime();
        this.overridePendingTransition(R.anim.animation_f_enter,
                R.anim.animation_f_leave);
    }

    private void getToTime() {

        c = Calendar.getInstance();
        System.out.println("toTime " + c.getTime());

        df = new SimpleDateFormat("HH:mm:ss");
        toTime = df.format(c.getTime());
        Log.e("toTime", toTime);

        finalTime = UtilService.getTimeInterval(this,df,fromTime,toTime);
        if (StorePreference.getInstance(this).getBooleanValue(GlobalData.ISDSELOGIN))
            sendHitCountToServer();

    }

    @Override
    public void loadComplete(int nbPages) {
        progressBar.setVisibility(View.GONE);
    }

    @Override
    public void onPageChanged(int page, int pageCount) {
        if (page + 1 == pageCount) {
            if (!CONTENT.getStatus().trim().equalsIgnoreCase("2")) {
                updateStatus("2");
            }
        } else {
            if (!CONTENT.getStatus().trim().equalsIgnoreCase("1") && !CONTENT.getStatus().trim().equalsIgnoreCase("2")) {
                updateStatus("1");
            }
        }
    }

    private void updateStatus(String status) {
        CONTENT.setStatus(status);
        if (new UtilService().isNetworkAvailable(PdfViewActivity.this)) {
            try {
                HashMap<String, String> map = new HashMap<>();
                map.put("contentid", CONTENT.getContentid());
                map.put("assettopicid", CONTENT.getAssettopicid());
                map.put("status", status);

                restService.updateContentStaus(map).enqueue(new MyCallback<ErrorResponse>(status) {
                    @Override
                    public void onResponse(Call<ErrorResponse> call, Response<ErrorResponse> response) {
                        if (response.body() != null && response.body().getStatus() == 200) {
                            CONTENT.setStatus(ids);
                        } else if (response.body() != null && response.body().getStatus() == 401) {
                            GlobalData.canLogout = true;
                            finish();
                        } else if (response.errorBody() != null) {
                            Gson gson = new Gson();
                            ErrorResponse message = gson.fromJson(response.errorBody().charStream(), ErrorResponse.class);
                            GlobalData.showToast(getBaseContext(), message.getMessage(), Toast.LENGTH_SHORT).show();
                            if (message.getStatus() == 401) {
                                GlobalData.canLogout = true;
                                finish();
                            }
                        }
                    }

                    @Override
                    public void onFailure(Call<ErrorResponse> call, Throwable t) {

                    }
                });

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

    @Override
    public void onPageError(int page, Throwable t) {
        progressBar.setVisibility(View.GONE);
        GlobalData.showToast(this, "Error", Toast.LENGTH_SHORT).show();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (GlobalData.canLogout) {
            finish();
        }
    }
}