/* -*- mode: jde; c-basic-offset: 2; indent-tabs-mode: nil -*- */

/*
  ZPUinoUploader - uploader implementation for ZPUino

  Copyright (c) 2010
  Alvaro Lopes

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  This program 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 General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software Foundation,
  Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  
  $Id$
*/

package processing.app.debug;

import processing.app.Base;
import processing.app.Preferences;
import processing.app.Serial;

import java.io.*;
import java.util.*;
import java.util.zip.*;
import javax.swing.*;
import gnu.io.*;


public class ZPUinoUploader extends Uploader  {
  public ZPUinoUploader() {
  }

  // XXX: add support for uploading sketches using a programmer
  public boolean uploadUsingPreferences(String buildPath, String className, boolean verbose)
  throws RunnerException {
    this.verbose = verbose;
    Map<String, String> boardPreferences = Base.getBoardPreferences();
    String uploadUsing = boardPreferences.get("upload.using");
    if (uploadUsing == null) {
      // fall back on global preference
      uploadUsing = Preferences.get("upload.using");
    }
    if (uploadUsing.equals("bootloader")) {
      return uploadViaBootloader(buildPath, className);
    } else {
      Target t;

      if (uploadUsing.indexOf(':') == -1) {
        t = Base.getTarget(); // the current target (associated with the board)
      } else {
        String targetName = uploadUsing.substring(0, uploadUsing.indexOf(':'));
        t = Base.targetsTable.get(targetName);
        uploadUsing = uploadUsing.substring(uploadUsing.indexOf(':') + 1);
      }

      Collection params = getProgrammerCommands(t, uploadUsing);

      params.add("-b" + buildPath + File.separator + Base.getFileNameWithoutExtension(new File(className)) + ".bin");
      return zpuinoprogrammer(params);
    }
  }
  
  private boolean uploadViaBootloader(String buildPath, String className)
  throws RunnerException {
    Map<String, String> boardPreferences = Base.getBoardPreferences();
    List commandDownloader = new ArrayList();

    commandDownloader.add(
      "-d" + (Base.isWindows() ? "\\\\.\\" : "") + Preferences.get("serial.port"));

    commandDownloader.add("-b" + buildPath + File.separator + Base.getFileNameWithoutExtension(new File(className)) + ".bin");

    return zpuinoprogrammer(commandDownloader);
  }
  
  public boolean burnBootloader(String targetName, String programmer) throws RunnerException {
    return burnBootloader(getProgrammerCommands(Base.targetsTable.get(targetName), programmer));
  }
  
  private Collection getProgrammerCommands(Target target, String programmer) {
    Map<String, String> programmerPreferences = target.getProgrammers().get(programmer);
    List params = new ArrayList();
    params.add("-c" + programmerPreferences.get("protocol"));
    
    if ("usb".equals(programmerPreferences.get("communication"))) {
      params.add("-Pusb");
    } else if ("serial".equals(programmerPreferences.get("communication"))) {
      params.add("-P" + (Base.isWindows() ? "\\\\.\\" : "") + Preferences.get("serial.port"));
      if (programmerPreferences.get("speed") != null) {
	params.add("-b" + Integer.parseInt(programmerPreferences.get("speed")));
      }
    }
    // XXX: add support for specifying the port address for parallel
    // programmers, although avrdude has a default that works in most cases.
    
    if (programmerPreferences.get("force") != null &&
        programmerPreferences.get("force").toLowerCase().equals("true"))
      params.add("-F");
    
    if (programmerPreferences.get("delay") != null)
      params.add("-i" + programmerPreferences.get("delay"));
    
    return params;
  }
  
  protected boolean burnBootloader(Collection params)
    throws RunnerException {
      return false;
  }
  
  public boolean zpuinoprogrammer(Collection p1, Collection p2) throws RunnerException {
    ArrayList p = new ArrayList(p1);
    p.addAll(p2);
    return zpuinoprogrammer(p);
  }
  
  public boolean zpuinoprogrammer(Collection params) throws RunnerException {
    List commandDownloader = new ArrayList();
    commandDownloader.add("zpuinoprogrammer");

    commandDownloader.addAll(params);

    return executeUploadCommand(commandDownloader);
  }
}

@@ -2822,24 +2822,65 @@
  + %22.bin%22);%0A
+    commandDownloader.add(%22-R%22); // Reset
 %0A    return 

use serial reset