package com.theta.helper;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.annotation.NonNull;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.util.Date;
import java.util.List;

import jp.agentec.abook.abv.bl.common.constant.ABookValues;
import jp.agentec.abook.abv.bl.common.log.Logger;
import jp.agentec.adf.util.DateTimeUtil;

/**
 * @version 1.2.300
 * THETAカメラ関連ヘルパークラス
 *
 * @author kimjinsung
 */
public class ThetaHelper {

    private static final String TAG = "ThetaHelper";
    private static final String THETA_IMAGE_SAVE_PATH = Environment.getExternalStorageDirectory() + "/" + Environment.DIRECTORY_PICTURES + "/RICOH THETA/";
    private Context mContext;

    public ThetaHelper(Context context) {
        mContext = context;
    }

    /**
     * THETAカメラWi-Fi接続
     * @param networkId ネットワークID
     * @return true:接続成功、false:接続失敗
     */
    public boolean connectThetaCameraWifi(int networkId) {
        WifiManager wifiManager = (WifiManager)mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager == null) {
            Logger.e(TAG, "wifiManager == null");
            return false;
        }
        //既存接続中のネットワーク切断
        WifiInfo wifi_inf = wifiManager.getConnectionInfo();
        if (wifi_inf.getNetworkId() != -1 ) {
            wifiManager.disableNetwork(wifi_inf.getNetworkId());
        }
        return wifiManager.enableNetwork(networkId, true);
    }

    /**
     * THETAカメラWi-Fi接続
     * @param ssid ネットワーク SSID
     * @return networkIdを返す(-1は失敗)
     */
    public int saveThetaCameraWifi(String ssid) {
        WifiManager wifiManager = (WifiManager)mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager == null) {
            Logger.e(TAG, "wifiManager == null");
            return -1;
        }

        //保存する前にSSIDがWi-Fiリストに存在するかチェック
        if (!checkWifiNetwork(ssid)) {
            Logger.e(TAG, "wifi list not found ssid = " + ssid);
            return -1;
        }

        String password = getPassword(ssid);

        //Wi-Fi情報を保存
        WifiConfiguration config = new WifiConfiguration();
        config.SSID = "\"" + ssid + "\"";
        config.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
        config.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
        config.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
        config.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
        config.preSharedKey = "\"" + password + "\"";
        int networkId = wifiManager.addNetwork(config); // 失敗した場合は-1となります
        if (networkId != -1) {
            wifiManager.saveConfiguration();
            wifiManager.updateNetwork(config);
        }
        return networkId;
    }

    /**
     * SSIDがAndroid端末のWifiリストに存在するかチェック
     * @param ssid アクセスポイント
     * @return 存在有無(true:存在する,false:存在しない)
     */
    private boolean checkWifiNetwork(String ssid) {
        WifiManager wifiManager = (WifiManager)mContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
        if (wifiManager == null) {
            Logger.e(TAG, "wifiManager == null");
            return false;
        }

        wifiManager.startScan();
        boolean hasWifiList = false;
        for (ScanResult scanResult : wifiManager.getScanResults()) {
            String scanResultSSID = scanResult.SSID.replace("\"", "");
            int index = scanResultSSID.indexOf(ssid);
            Logger.d(TAG, "scanResultSSID = " + scanResultSSID);
            if (index != -1) {
                hasWifiList = true;
            }
        }
        return hasWifiList;
    }

    /**
     * SSIDからパスワード情報を取り出す
     * @param ssid アクセスポイント
     * @return 接続パスワード
     */
    public String getPassword(String ssid) {
        String password = ssid.replace("THETA","");
        password = password.replace(".OSC","");
        return password.substring(2);
    }

    /**
     * Thetaカメラから選択した画像をローカルフォットライブラリに保存
     * @param bitmap 選択した画像データ
     * @param fileId Thetaカメラの選択したファイルパス
     * @return 保存結果(true:成功、false:失敗)
     */
    public boolean thetaImageLocalSave(Bitmap bitmap, String fileId) {
        boolean isSuccess = false;
        try {
            File file = new File(fileId);
            // 日付をファイル名につける。
            String fileName = DateTimeUtil.toString_yyyyMMddHHmmss_none(new Date()) + "_" + file.getName();
            //[/storage/emulated/0/Pictures/RICOH THETA/]ファイル保存フォルダ指定及び作成
            String saveFullPath = THETA_IMAGE_SAVE_PATH + fileName;
            File thetaSavePathFile = new File(THETA_IMAGE_SAVE_PATH);
            if (!thetaSavePathFile.exists()) {
                thetaSavePathFile.mkdir();
                if (!thetaSavePathFile.mkdirs()) {
                    Logger.e(TAG, "Directory not created");
                    return false;
                }
            }
            // 保存処理開始
            FileOutputStream fos = new FileOutputStream(new File(thetaSavePathFile, fileName));
            // jpegで保存
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            // 保存処理終了
            fos.close();
            // アルバムに反映
            addGallery(fileName, saveFullPath);
            isSuccess = true;
        } catch (Exception e) {
            Logger.e(TAG, e.toString());
        }
        return isSuccess;

    }
    /**
     * 保存した画像をギャラリーに追加
     * @param fileName 保存ファイル名
     * @param fileFullPath 保存フルファイルパス
     */
    private void addGallery(String fileName, String fileFullPath) {
        try {
            ContentValues values = new ContentValues();
            ContentResolver contentResolver = mContext.getContentResolver();
            values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
            values.put(MediaStore.MediaColumns.TITLE, fileName);
            values.put("_data", fileFullPath);
            contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        } catch (Exception e) {
            Logger.e(TAG, e.toString());
        }
    }

    /**
     * Imageファイルが転送済みかのチェック
     * @param fileName Theta Image FileName
     * @return 転送結果(true:転送済み)
     */
    public boolean transferredImage(final String fileName) {
        final File imageFile = new File(fileName);
        File savePath = new File(THETA_IMAGE_SAVE_PATH);
        File[] saveImageFiles = savePath.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {
                return name.endsWith(imageFile.getName());
            }
        });

        return saveImageFiles.length != 0;
    }

    /**
     * ThetaカメラとWi-Fi接続状態をチェック
     * @param wifiManager Wifiマネージャー
     * @return true:接続状態、false:非接続状態
     */
    public boolean checkThetaCameraWifiConnected(@NonNull WifiManager wifiManager) {
        List<ScanResult> results = wifiManager.getScanResults();
        boolean isConnected = false;
        for (ScanResult scanResult : results) {
            String scanSSID = scanResult.SSID.replace("\"", "");
            Logger.d(TAG, "*****scanSSID = " + scanSSID);
            if (scanSSID.length() != 0) {
                int index = scanSSID.indexOf(ABookValues.THETA_MODEL_NAME_THETA);
                if (index != -1) {
                    for (WifiConfiguration configuration : wifiManager.getConfiguredNetworks()) {
                        // Android4.2以降よりダブルクォーテーションが付いてくるので除去
                        String configurationSSID = configuration.SSID.replace("\"", "");
                        if (configurationSSID.equals(scanSSID)) {
                            if (configuration.status == WifiConfiguration.Status.CURRENT) {
                                isConnected = true;
                            }
                            break;
                        }
                    }
                    if (isConnected) {
                        break;
                    }
                }
            }
        }
        return isConnected;
    }

    /**
     * THETAカメラWi-Fiと非接続
     */
    public void disConnectThetaCameraWifi(WifiManager wifiManager) {
        Logger.d(TAG,"disConnectThetaCameraWifi");
        //既存接続中のネットワーク切断
        WifiInfo wifi_inf = wifiManager.getConnectionInfo();
        if (wifi_inf.getNetworkId() != -1 ) {
            wifiManager.disableNetwork(wifi_inf.getNetworkId());
            wifiManager.disconnect();
        }
        wifiManager.disconnect();
    }


    /**
     * ConnectivityManagerを利用してアプリ(プロセス)全体のネットワークを設定します。
     */
    public void appConnectedWifiOnly() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (connectivityManager != null) {
                if (connectivityManager.getAllNetworks().length > 1) {
                    for (Network net : connectivityManager.getAllNetworks()) {
                        NetworkInfo networkInfo = connectivityManager.getNetworkInfo(net);
                        if (networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
                            connectivityManager.bindProcessToNetwork(net);
                            break;
                        }
                    }
                }
            }
        }
    }

    /**
     * ConnectivityManagerを利用してアプリ(プロセス)全体のネットワークを解除する。
     */
    public void appConnectedWifiDefault() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (connectivityManager != null) {
                if (connectivityManager.getBoundNetworkForProcess() != null) {
                    connectivityManager.bindProcessToNetwork(null);
                }
            }
        }
    }
}