/*
 * Copyright (C) 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.googlecode.android_scripting.facade;

import android.app.Service;
import android.content.Context;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiScanner.HotspotInfo;
import android.os.Bundle;
import android.os.SystemClock;

import com.googlecode.android_scripting.Log;
import com.googlecode.android_scripting.MainThread;
import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
import com.googlecode.android_scripting.rpc.Rpc;
import com.googlecode.android_scripting.rpc.RpcParameter;
import com.googlecode.android_scripting.rpc.RpcStartEvent;
import com.googlecode.android_scripting.rpc.RpcStopEvent;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WifiScanner functions.
 *
 */
public class WifiScannerFacade extends RpcReceiver {
  private final Service mService;
  private final EventFacade mEventFacade;
  private final WifiScanner mScan;
  //These counters are just for indexing;
  //they do not represent the total number of listeners
  private static int WifiScanListenerCnt;
  private static int WifiChangeListenerCnt;
  private static int WifiHotspotListenerCnt;
  private final ConcurrentHashMap<Integer, WifiScanListener> wifiScannerListenerList;
  private final ConcurrentHashMap<Integer, ChangeListener> wifiChangeListenerList;
  private final ConcurrentHashMap<Integer, WifiHotspotListener> wifiHotspotListenerList;
  private static ConcurrentHashMap<Integer, ScanResult[]> wifiScannerResultList;

  public WifiScannerFacade(FacadeManager manager) {
    super(manager);
    mService = manager.getService();
    mScan = (WifiScanner) mService.getSystemService(Context.WIFI_SCANNING_SERVICE);
    mEventFacade = manager.getReceiver(EventFacade.class);
    wifiScannerListenerList = new ConcurrentHashMap<Integer, WifiScanListener>();
    wifiChangeListenerList = new ConcurrentHashMap<Integer, ChangeListener>();
    wifiHotspotListenerList = new ConcurrentHashMap<Integer, WifiHotspotListener>();
    wifiScannerResultList = new ConcurrentHashMap<Integer, ScanResult[]>();
  }

  public static List<ScanResult> getWifiScanResult(Integer listener_index, List<ScanResult> scanResults){
    synchronized (wifiScannerResultList) {
      ScanResult[] scanArray = wifiScannerResultList.get(listener_index);
      if (scanArray != null){
        for(ScanResult scanresult :  scanArray)
          scanResults.add(scanresult);
      }
      return scanResults;
    }
  }

  private class WifiActionListener implements WifiScanner.ActionListener {
    private final Bundle mResults;
    public int mIndex;
    protected String mEventType;

    public WifiActionListener(String type, int idx, Bundle resultBundle) {
      this.mIndex = idx;
      this.mEventType = type;
      this.mResults = resultBundle;
    }

    @Override
    public void onSuccess() {
      Log.d("onSuccess " + mEventType + " " + mIndex);
      mResults.putString("Type", "onSuccess");
      mResults.putLong("Realtime", SystemClock.elapsedRealtime());
      mEventFacade.postEvent(mEventType + mIndex, mResults.clone());
      mResults.clear();
    }

    @Override
    public void onFailure(int reason, String description) {
      Log.d("onFailure " + mEventType + " " + mIndex);
      mResults.putString("Type", "onFailure");
      mResults.putInt("Reason", reason);
      mResults.putString("Description", description);
      mEventFacade.postEvent(mEventType + mIndex, mResults.clone());
      mResults.clear();
    }

    public void reportResult(ScanResult[] results, String type) {
      Log.d("reportResult "+ mEventType + " "+ mIndex);
      mResults.putLong("Timestamp", System.currentTimeMillis()/1000);
      mResults.putString("Type", type);
      mResults.putParcelableArray("Results", results);
      mEventFacade.postEvent(mEventType + mIndex, mResults.clone());
      mResults.clear();
    }
  }

  /**
   * Constructs a wifiScanListener obj and returns it
   * @return WifiScanListener
   */
  private WifiScanListener genWifiScanListener() {
    WifiScanListener mWifiScannerListener = MainThread.run(mService,
      new Callable<WifiScanListener>() {
        @Override
        public WifiScanListener call() throws Exception {
          return new WifiScanListener();
        }
      });
    wifiScannerListenerList.put(mWifiScannerListener.mIndex, mWifiScannerListener);
    return mWifiScannerListener;
  }

  private class WifiScanListener implements WifiScanner.ScanListener {
    private static final String mEventType =  "WifiScannerScan";
    protected final Bundle mScanResults;
    private final WifiActionListener mWAL;
    public int mIndex;

    public WifiScanListener() {
      mScanResults = new Bundle();
      WifiScanListenerCnt += 1;
      mIndex = WifiScanListenerCnt;
      mWAL = new WifiActionListener(mEventType, mIndex, mScanResults);
    }

    @Override
    public void onSuccess() {
      mWAL.onSuccess();
    }

    @Override
    public void onFailure(int reason, String description) {
      wifiScannerListenerList.remove(mIndex);
      mWAL.onFailure(reason, description);
    }

    @Override
    public void onPeriodChanged(int periodInMs) {
      Log.d("onPeriodChanged " + mEventType + " " + mIndex);
      mScanResults.putString("Type", "onPeriodChanged");
      mScanResults.putInt("NewPeriod", periodInMs);
      mEventFacade.postEvent(mEventType + mIndex, mScanResults.clone());
      mScanResults.clear();
    }

    @Override
    public void onResults(ScanResult[] results) {
      wifiScannerResultList.put(mIndex, results);
      mWAL.reportResult(results, "onResults");
    }

    @Override
    public void onFullResult(ScanResult fullScanResult) {
      Log.d("onFullResult WifiScanListener " + mIndex);
      mWAL.reportResult(new ScanResult[]{fullScanResult}, "onFullResult");
    }
  }

  /**
   * Constructs a ChangeListener obj and returns it
   * @return ChangeListener
   */
  public ChangeListener genWifiChangeListener() {
    ChangeListener mWifiChangeListener = MainThread.run(mService, new Callable<ChangeListener>() {
      @Override
      public ChangeListener call() throws Exception {
        return new ChangeListener();
      }
    });
    wifiChangeListenerList.put(mWifiChangeListener.mIndex, mWifiChangeListener);
    return mWifiChangeListener;
  }

  private class ChangeListener implements WifiScanner.WifiChangeListener {
    private static final String mEventType =  "WifiScannerChange";
    protected final Bundle mResults;
    private final WifiActionListener mWAL;
    public int mIndex;

    public ChangeListener() {
      mResults = new Bundle();
      WifiChangeListenerCnt += 1;
      mIndex = WifiChangeListenerCnt;
      mWAL = new WifiActionListener(mEventType, mIndex, mResults);
    }

    @Override
    public void onSuccess() {
      mWAL.onSuccess();
    }

    @Override
    public void onFailure(int reason, String description) {
      wifiChangeListenerList.remove(mIndex);
      mWAL.onFailure(reason, description);
    }
    /** indicates that changes were detected in wifi environment
     * @param results indicate the access points that exhibited change
     */
    @Override
    public void onChanging(ScanResult[] results) {           /* changes are found */
      mWAL.reportResult(results, "onChanging");
    }
    /** indicates that no wifi changes are being detected for a while
     * @param results indicate the access points that are bing monitored for change
     */
    @Override
    public void onQuiescence(ScanResult[] results) {         /* changes settled down */
      mWAL.reportResult(results, "onQuiescence");
    }
  }

  public WifiHotspotListener genWifiHotspotListener() {
    WifiHotspotListener mWifiHotspotListener = MainThread.run(mService, new Callable<WifiHotspotListener>() {
      @Override
      public WifiHotspotListener call() throws Exception {
        return new WifiHotspotListener();
      }
    });
    wifiHotspotListenerList.put(mWifiHotspotListener.mIndex, mWifiHotspotListener);
    return mWifiHotspotListener;
  }

  private class WifiHotspotListener implements WifiScanner.HotspotListener {
    private static final String mEventType =  "WifiScannerHotspot";
    protected final Bundle mResults;
    private final WifiActionListener mWAL;
    public int mIndex;

    public WifiHotspotListener() {
      mResults = new Bundle();
      WifiHotspotListenerCnt += 1;
      mIndex = WifiHotspotListenerCnt;
      mWAL = new WifiActionListener(mEventType, mIndex, mResults);
    }

    @Override
    public void onSuccess() {
      mWAL.onSuccess();
    }

    @Override
    public void onFailure(int reason, String description) {
      wifiHotspotListenerList.remove(mIndex);
      mWAL.onFailure(reason, description);
    }

    @Override
    public void onFound(ScanResult[] results) {
      mWAL.reportResult(results, "onHotspotFound");
    }
  }

  /** RPC Method Section */

  /**
   * Starts periodic WifiScanner scan
   * @param periodInMs
   * @param channel_freqs frequencies of channels to scan
   * @return the id of the scan listener associated with this scan
   */
  @Rpc(description = "Starts a periodic WifiScanner scan")
  @RpcStartEvent("WifiScannerScan")
  public Integer startWifiScannerScan(@RpcParameter(name = "periodInMs") Integer periodInMs,
                                  @RpcParameter(name = "channel_freqs") Integer[] channel_freqs) {
    WifiScanner.ScanSettings ss = new WifiScanner.ScanSettings();
    ss.channels = new WifiScanner.ChannelSpec[channel_freqs.length];
    for(int i=0; i<channel_freqs.length; i++) {
      ss.channels[i] = new WifiScanner.ChannelSpec(channel_freqs[i]);
    }
    ss.periodInMs = periodInMs;
    Log.d("startWifiScannerScan periodInMs " + ss.periodInMs);
    for(int i=0; i<ss.channels.length; i++) {
      Log.d("startWifiScannerScan " + ss.channels[i].frequency + " " + ss.channels[i].passive + " " + ss.channels[i].dwellTimeMS);
    }
    WifiScanListener mListener = genWifiScanListener();
    mScan.startBackgroundScan(ss, mListener);
    return mListener.mIndex;
  }

  /**
   * Stops a WifiScanner scan
   * @param listener_mIndex the id of the scan listener whose scan to stop
   * @throws Exception
   */
  @Rpc(description = "Stops an ongoing periodic WifiScanner scan")
  @RpcStopEvent("WifiScannerScan")
  public void stopWifiScannerScan(@RpcParameter(name = "listener") Integer listener_index) throws Exception {
    if(!wifiScannerListenerList.containsKey(listener_index)) {
      throw new Exception("Background scan session " + listener_index + " does not exist");
    }
    WifiScanListener mListener = wifiScannerListenerList.get(listener_index);
    Log.d("stopWifiScannerScan mListener "+ mListener.mIndex );
    mScan.stopBackgroundScan(mListener);
    wifiScannerResultList.remove(listener_index);
    wifiScannerListenerList.remove(listener_index);
  }

  @Rpc(description = "Returns a list of mIndexes of existing listeners")
  public Integer[] showWifiScanListeners() {
    Integer[] result = new Integer[wifiScannerListenerList.size()];
    int j = 0;
    for(int i : wifiScannerListenerList.keySet()) {
      result[j] = wifiScannerListenerList.get(i).mIndex;
      j += 1;
    }
    return result;
  }

  /**
   * Starts tracking wifi changes
   * @return the id of the change listener associated with this track
   */
  @Rpc(description = "Starts tracking wifi changes")
  public Integer startTrackingChange() {
    Log.d("starting change track");
    ChangeListener mListener = genWifiChangeListener();
    mScan.startTrackingWifiChange(mListener);
    return mListener.mIndex;
  }

  /**
   * Stops tracking wifi changes
   * @param listener_index the id of the change listener whose track to stop
   * @throws Exception
   */
  @Rpc(description = "Stops tracking wifi changes")
  public void stopTrackingChange(@RpcParameter(name = "listener") Integer listener_index) throws Exception {
    if(!wifiChangeListenerList.containsKey(listener_index)) {
      throw new Exception("Wifi change tracking session " + listener_index + " does not exist");
    }
    ChangeListener mListener = wifiChangeListenerList.get(listener_index);
    mScan.stopTrackingWifiChange(mListener);
    wifiChangeListenerList.remove(listener_index);
  }

  /**
   * Starts tracking changes of the wifi networks specified in a list of hotspots
   * @param hotspotInfos a list specifying which wifi networks to track
   * @param apLostThreshold signal strength below which an AP is considered lost
   * @return the id of the hotspot listener associated with this track
   * @throws Exception
   */
  @Rpc(description = "Starts tracking changes in the APs specified by the list")
  public Integer startTrackingHotspots(String[] hotspotInfos, Integer apLostThreshold) throws Exception {
    //Instantiates HotspotInfo objs
    HotspotInfo[] mHotspotInfos = new HotspotInfo[hotspotInfos.length];
    for(int i=0; i<hotspotInfos.length; i++) {
      Log.d("android_scripting " + hotspotInfos[i]);
      String[] tokens = hotspotInfos[i].split(" ");
      if(tokens.length!=3) {
        throw new Exception("Invalid hotspot info: "+hotspotInfos[i]);

      }
      int a = Integer.parseInt(tokens[1]);
      int b = Integer.parseInt(tokens[2]);
      HotspotInfo mHI = new HotspotInfo();
      mHI.bssid = tokens[0];
      mHI.low = a<b ? a:b;
      mHI.high = a<b ? b:a;
      mHotspotInfos[i] = mHI;
    }
    WifiHotspotListener mWHL = genWifiHotspotListener();
    mScan.startTrackingHotspots(mHotspotInfos, apLostThreshold, mWHL);
    return mWHL.mIndex;
  }

  /**
   * Stops tracking the list of APs associated with the input listener
   * @param listener_index the id of the hotspot listener whose track to stop
   * @throws Exception 
   */
  @Rpc(description = "Stops tracking changes in the APs on the list")
  public void stopTrackingHotspots(@RpcParameter(name = "listener") Integer listener_index) throws Exception {
    if(!wifiHotspotListenerList.containsKey(listener_index)) {
      throw new Exception("Hotspot tracking session " + listener_index + " does not exist");
    }
    WifiHotspotListener mListener = wifiHotspotListenerList.get(listener_index);
    mScan.stopTrackingHotspots(mListener);
    wifiHotspotListenerList.remove(listener_index);
  }

  /**
   * Shuts down all activities associated with WifiScanner
   */
  @Rpc(description = "Shuts down all WifiScanner activities")
  public void wifiScannerShutdown() {
    this.shutdown();
  }

  /**
   * Stops all activity
   */
  @Override
  public void shutdown() {
    try {
      if(!wifiScannerListenerList.isEmpty()) {
        for(int i : wifiScannerListenerList.keySet()) {
          this.stopWifiScannerScan(i);
        }
      }
      if(!wifiChangeListenerList.isEmpty()) {
        for(int i : wifiChangeListenerList.keySet()) {
          this.stopTrackingChange(i);
        }
      }
      if(!wifiHotspotListenerList.isEmpty()) {
        for(int i : wifiHotspotListenerList.keySet()) {
          this.stopTrackingHotspots(i);
        }
      }
    } catch (Exception e) {
      Log.e("Shutdown failed: " + e.toString());
    }
  }
}
