package org.hsbp.spalarm.android;

import android.app.Activity;
import android.app.TimePickerDialog;
import android.content.Context;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.*;

import java.io.IOException;
import java.util.Set;
import java.util.ArrayList;

import yuku.ambilwarna.AmbilWarnaDialog;

public class Main extends Activity implements
    AmbilWarnaDialog.OnAmbilWarnaListener, TimePickerDialog.OnTimeSetListener
{
    private int currentColor = Color.WHITE;
    private int hourOfDay = 6;
    private int minuteOfHour = 20;
    private final static String CURRENT_COLOR = "org.hsbp.spalarm.android.Main.CURRENT_COLOR";
    private final static String HOUR_OF_DAY = "org.hsbp.spalarm.android.Main.HOUR_OF_DAY";
    private final static String MINUTE_OF_HOUR = "org.hsbp.spalarm.android.Main.MINUTE_OF_HOUR";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        updatePreview();
        loadDevices(null);
    }

    @Override
    protected void onSaveInstanceState(final Bundle outState) {
        outState.putInt(CURRENT_COLOR, currentColor);
        outState.putInt(HOUR_OF_DAY, hourOfDay);
        outState.putInt(MINUTE_OF_HOUR, minuteOfHour);
        super.onSaveInstanceState(outState);
    }

    @Override
    protected void onRestoreInstanceState(final Bundle savedInstanceState) {
        currentColor = savedInstanceState.getInt(CURRENT_COLOR);
        hourOfDay = savedInstanceState.getInt(HOUR_OF_DAY);
        minuteOfHour = savedInstanceState.getInt(MINUTE_OF_HOUR);
        super.onRestoreInstanceState(savedInstanceState);
        updatePreview();
    }

    private void updatePreview() {
        final TextView preview = (TextView)findViewById(R.id.preview);
        preview.setText(String.format("%d:%02d", hourOfDay, minuteOfHour));
        preview.setTextColor(isDarkColor(currentColor) ? Color.WHITE : Color.BLACK);
        preview.setBackgroundColor(currentColor);
    }

    private static boolean isDarkColor(int color) {
        final float[] hsv = new float[3];
        Color.colorToHSV(color, hsv);
        return hsv[2] < 0.5;
    }

    public void selectColor(final View v) {
        new AmbilWarnaDialog(this, currentColor, this).show();
    }

    public void selectTime(final View v) {
        new TimePickerDialog(this, this, hourOfDay, minuteOfHour, true).show();
    }

    public void loadDevices(final View v) {
        new LoadDevicesTask().execute(this);
    }

    public void setAlarm(final View v) {
        final Spinner deviceList = (Spinner)findViewById(R.id.devices);
        final Device dev = (Device)deviceList.getSelectedItem();
        if (dev == null) {
            Toast.makeText(Main.this, deviceList.getCount() > 0 ?
                    "Please select a Spark.io Alarm Clock from the list" :
                    "Touch the Refresh list button!",
                    Toast.LENGTH_SHORT).show();
            return;
        }
        new SetAlarmTask().execute(dev);
    }

    @Override
    public void onOk(final AmbilWarnaDialog dialog, final int color) {
        currentColor = color;
        updatePreview();
    }

    @Override
    public void onCancel(final AmbilWarnaDialog dialog) { /* ignore */ }

    @Override
    public void onTimeSet(final TimePicker view, final int hourOfDay, final int minute) {
        this.hourOfDay = hourOfDay;
        this.minuteOfHour = minute;
        updatePreview();
    }

    private class SetAlarmTask extends AsyncTask<Device, Void, Boolean> {
        @Override
        protected Boolean doInBackground(final Device... dev) {
            try {
                return dev[0].setAlarm(currentColor, hourOfDay, minuteOfHour);
            } catch (IOException ioe) {
                return Boolean.FALSE;
            }
        }

        @Override
        protected void onPostExecute(final Boolean result) {
            Toast.makeText(Main.this, result.booleanValue() ?
                    "The alarm has been set." : "An error occured.",
                    Toast.LENGTH_SHORT).show();
        }
    }

    private class LoadDevicesTask extends AsyncTask<Context, Void, Set<Device>> {
        @Override
        protected Set<Device> doInBackground(final Context... ctx) {
            try {
                return Device.discover(ctx[0]);
            } catch (IOException ioe) {
                return null;
            }
        }

        @Override
        protected void onPostExecute(final Set<Device> devices) {
            if (devices == null) {
                Toast.makeText(Main.this, "Network error, is your WiFi turned on?",
                        Toast.LENGTH_SHORT).show();
                return;
            }
            final Spinner ui = (Spinner)findViewById(R.id.devices);
            ArrayAdapter<Device> adapter = new ArrayAdapter<Device>(Main.this,
                    android.R.layout.simple_spinner_item, new ArrayList<Device>(devices));
            adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
            ui.setAdapter(adapter);
        }
    }
}

@@ -179,43 +179,9 @@
 .os.
-AsyncTask;%0Aimport android.os.Bundle
+*
 ;%0Aim
@@ -587,16 +587,59 @@
 r = 20;%0A
+    private ArrayList%3CParcelable%3E devList;%0A
     priv
@@ -912,16 +912,107 @@
 F_HOUR%22;
+%0A    private final static String DEVICE_LIST = %22org.hsbp.spalarm.android.Main.DEVICE_LIST%22;
 %0A%0A    /*
@@ -1503,32 +1503,95 @@
  minuteOfHour);%0A
+        outState.putParcelableArrayList(DEVICE_LIST, devList);%0A
         super.on
@@ -1842,16 +1842,16 @@
 F_DAY);%0A
-
         
@@ -1904,24 +1904,100 @@
 E_OF_HOUR);%0A
+        updateList(savedInstanceState.getParcelableArrayList(DEVICE_LIST));%0A
         supe
@@ -5128,24 +5128,185 @@
       %7D%0A    
+        updateList(new ArrayList%3CParcelable%3E(devices));%0A        %7D%0A    %7D%0A%0A    private void updateList(final ArrayList%3CParcelable%3E devs) %7B%0A        devList = devs;%0A
         fina
@@ -5365,20 +5365,16 @@
         
-   
- 
 ArrayAda
@@ -5378,21 +5378,25 @@
 Adapter%3C
-Devic
+Parcelabl
 e%3E adapt
@@ -5417,21 +5417,25 @@
 Adapter%3C
-Devic
+Parcelabl
 e%3E(Main.
@@ -5440,20 +5440,16 @@
 n.this,%0A
-    
         
@@ -5498,45 +5498,18 @@
 em, 
-new ArrayList%3CDevice%3E(devices));%0A    
+devList);%0A
     
@@ -5600,20 +5600,16 @@
         
-    
 ui.setAd
@@ -5624,26 +5624,16 @@
 apter);%0A
-        %7D%0A
     %7D%0A%7D%0A

save device list upon configuration change