/*******************************************************************************
 * Copyright (C) 2015, 2016 RAPID EU Project
 *
 * This library is free software; you can redistribute it and/or modify it under the terms of the
 * GNU Lesser General Public License as published by the Free Software Foundation; either version
 * 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with this library;
 * if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *******************************************************************************/
package eu.project.rapid.demo;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Color;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.TextView;
import android.widget.Toast;

import com.squareup.otto.Subscribe;

import java.io.IOException;
import java.security.Security;

import eu.project.rapid.ac.RapidNetworkService;
import eu.project.rapid.ac.profilers.DeviceProfiler;
import eu.project.rapid.bus.BusProvider;
import eu.project.rapid.common.RapidConstants.COMM_TYPE;
import eu.project.rapid.common.RapidUtils;
import eu.project.rapid.dtos.DeviceDTO;
import eu.project.rapid.dtos.DeviceMode;
import eu.project.rapid.dtos.OffloadingTaskDTO;
import eu.project.rapid.rest.RestClient;
import eu.project.rapid.storage.Preferences;

/**
 * The main activity for the Android program.
 */
public class MainActivity extends Activity {

    public static final String KEY_VM_IP = "KEY_VM_IP";
    public static final String KEY_USE_RAPID_INFRASTRUCTURE = "KEY_USE_RAPID_INFRASTRUCTURE";
    public static final String KEY_CONN_TYPE = "KEY_CONN_TYPE";
    public static final String KEY_USE_PREV_VM = "KEY_USE_PREV_VM";
    public static final String KEY_OFFLOADING_OBJ = "KEY_OFFLOADING_OBJ";
    public static final String KEY_TIME = "KEY_TIME";
    private static final String TAG = "MainActivity";

    static {
        Security.insertProviderAt(new org.spongycastle.jce.provider.BouncyCastleProvider(), 1);
    }

    DeviceProfiler deviceProfiler;
    long getSellerDeviceTime;
    private RadioGroup radioGroupStartAs;
    private RadioGroup radioGroupUseRapid;
    private EditText textVmIpAddress;
    private String vmIp;
    private COMM_TYPE commType = COMM_TYPE.SSL;
    private boolean connectToPrevVm = true;
    private TextView updatedJsonTV;
    private TextView balanceTV;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        deviceProfiler = new DeviceProfiler(MainActivity.this);
        //deviceProfiler.startDeviceProfiling();
        deviceProfiler.trackBatteryLevel();

        updatedJsonTV = (TextView) findViewById(R.id.updatedJsonTV);
        balanceTV = (TextView) findViewById(R.id.balanceTV);

        radioGroupUseRapid = (RadioGroup) findViewById(R.id.radioGroupUseRapid);
        radioGroupUseRapid.setOnCheckedChangeListener(new OnUseRapidRadioChecked());

        radioGroupStartAs = (RadioGroup) findViewById(R.id.radioGroupStartAs);
        radioGroupStartAs.setOnCheckedChangeListener(new OnStartAsRadioChecked());

        textVmIpAddress = (EditText) findViewById(R.id.editTextIpAddress);
        SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
        vmIp = prefs.getString(KEY_VM_IP, null);
        textVmIpAddress.setText(vmIp);

        updateBalanceView();

        //RestClient.getInstance(this).getAllDevices();
    }

    void updateBalanceView() {
        Long balance = Preferences.getCurrencyUnits(MainActivity.this);
        balanceTV.setText(String.format(getString(R.string.balance), Long.toString(balance)));
    }

    @Subscribe
    public void updateDeviceResultReceived(DeviceDTO deviceDTO) {
        Log.i("device Updated", " " + deviceDTO.getIp());
        Preferences.saveDeviceId(deviceDTO.getId(), MainActivity.this);
        Preferences.saveCurrencyUnits(deviceDTO.getCurrencyUnitsAvailable(), MainActivity.this);

        updatedJsonTV.setText(deviceDTO.toString());
        updateBalanceView();
    }

    @Subscribe
    public void onOffloadingDeviceReceived(OffloadingTaskDTO offloadingTaskDTO) {
        Log.i("OffloadingNodeReceived", " " + offloadingTaskDTO.getIp());
        textVmIpAddress.setText(offloadingTaskDTO.getIp());
        //textVmIpAddress.setText("192.168.0.101");

        launchActivity(offloadingTaskDTO, System.currentTimeMillis() - getSellerDeviceTime);

    }

    @Subscribe
    public void error(String error) {
        Toast.makeText(MainActivity.this, error, Toast.LENGTH_SHORT).show();
        //textVmIpAddress.setText("192.168.0.101");

        //TODO: Remove this code after testing
/*        OffloadingTaskDTO offloadingTaskDTO = new OffloadingTaskDTO();
        offloadingTaskDTO.setId(1L);
        offloadingTaskDTO.setIp("192.168.0.101");
        offloadingTaskDTO.setCost(28);
        launchActivity(offloadingTaskDTO);*/
    }

    @Override
    protected void onResume() {
        super.onResume();
        BusProvider.getInstance().register(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        BusProvider.getInstance().unregister(this);
    }

    public void onRadioCommunicationTypeChecked(View radioButton) {

        switch (radioButton.getId()) {

            case R.id.radio_clear_communication:
                commType = COMM_TYPE.CLEAR;
                Log.i(TAG, "The communication UE-VM should be performed in clear");
                break;

            case R.id.radio_ssl_communication:
                commType = COMM_TYPE.SSL;
                Log.i(TAG, "The communication UE-VM should be performed using SSL");
                break;
        }
    }

    // Watch for button clicks
    public void onStartButton(View v) {
        // Actual data size: 0.000936
        getSellerDeviceTime = System.currentTimeMillis();
        RestClient.getInstance(this).getSellerDevices(0.01, getDeviceDTO());
    }

    public void onUpdateButton(View view) {
        RestClient.getInstance(this).updateDevice(getDeviceDTO());
    }

    private DeviceDTO getDeviceDTO() {

        ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo();
        ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        activityManager.getMemoryInfo(mi);
        double availableMegs = mi.availMem / 0x100000L;

        //Percentage can be calculated for API 16+
        double percentAvail = mi.availMem / (double) mi.totalMem * 100.0;

        Log.d("availableMegs", " " + availableMegs);
        Log.d("percentAvail", " " + percentAvail);

        Log.d("Battery", " " + deviceProfiler.batteryLevel);

        try {
            Log.d("Max Frequency", " " + deviceProfiler.getMaxCpuFreq());
            Log.d("Current Frequency", " " + deviceProfiler.getCurrentCpuFreq());
        } catch (IOException e) {
            e.printStackTrace();
        }

        //TODO: do it for mobile connection as well
        Integer linkSpeed = null;
        WifiManager wifiManager = (WifiManager) getApplicationContext()
                .getSystemService(Context.WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
        if (wifiInfo != null) {
            linkSpeed = wifiInfo.getLinkSpeed();
            Log.d("linkSpeed", " " + linkSpeed);
        }

        try {
            Long id = Preferences.getDeviceId(MainActivity.this);

            DeviceDTO deviceDTO = new DeviceDTO();

            if (id != -1) {
                deviceDTO.setId(id);
            }

            Long balance = Preferences.getCurrencyUnits(MainActivity.this);

            if (balance != -1) {
                deviceDTO.setCurrencyUnitsAvailable(balance);
            }

            deviceDTO.setTotalMemory((int) mi.totalMem);
            deviceDTO.setRemainingMemory(mi.availMem);
            deviceDTO.setRemainingBattery(((double) deviceProfiler.batteryLevel) / 100);
            deviceDTO.setProcessorSpeed(deviceProfiler.getMaxCpuFreq());
            deviceDTO.setProcessorFree(deviceProfiler.getCurrentCpuFreq());
            deviceDTO.setNetworkBandWidthAvailable(linkSpeed);
            deviceDTO.setDeviceMode(DeviceMode.BUYER);

            return deviceDTO;

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

        return null;
    }

    private void launchActivity(OffloadingTaskDTO offloadingTaskDTO, long time) {

        Log.i("time", time + "");

        Intent intent = new Intent(MainActivity.this, DemoActivity.class);

        vmIp = textVmIpAddress.getText().toString();

        if (!RapidUtils.validateIpAddress(vmIp)) {
            textVmIpAddress.setTextColor(Color.RED);
        } else {
            textVmIpAddress.setTextColor(Color.GREEN);
            Log.i(TAG, "Creating a connection with VM with IP: " + vmIp);
            intent.putExtra(KEY_VM_IP, vmIp);
            intent.putExtra(KEY_USE_RAPID_INFRASTRUCTURE, false);
            intent.putExtra(KEY_CONN_TYPE, commType);
            intent.putExtra(KEY_TIME, time);
            intent.putExtra(KEY_USE_PREV_VM, connectToPrevVm);
            intent.putExtra(KEY_OFFLOADING_OBJ, offloadingTaskDTO);
            SharedPreferences prefs = getPreferences(Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = prefs.edit();
            editor.putString(KEY_VM_IP, vmIp);
            editor.apply();
            startActivity(intent);
        }

    }

    private class OnStartAsRadioChecked implements OnCheckedChangeListener {
        public void onCheckedChanged(RadioGroup group, int checkedId) {

            switch (checkedId) {
                case R.id.radioStartAsNewVm:
                    connectToPrevVm = false;
                    RapidNetworkService.usePrevVm = false;
                    break;

                case R.id.radioStartAsOldVm:
                    connectToPrevVm = true;
                    RapidNetworkService.usePrevVm = true;
                    break;

                case R.id.radioStartAsD2D:
                    break;
            }
        }
    }

    private class OnUseRapidRadioChecked implements OnCheckedChangeListener {

        public void onCheckedChanged(RadioGroup group, int checkedId) {
            switch (checkedId) {
                case R.id.radioUseRapidYes:
                    textVmIpAddress.setVisibility(View.GONE);
                    radioGroupStartAs.setVisibility(View.VISIBLE);
                    break;

                case R.id.radioUseRapidNo:
                    radioGroupStartAs.setVisibility(View.GONE);
                    textVmIpAddress.setVisibility(View.VISIBLE);
                    break;
            }
        }
    }
}
