/**
 * File:	modules/Modem.ycp
 * Package:	Network configuration
 * Summary:	Modem data
 * Authors:	Michal Svec <msvec@suse.cz>
 *
 * $Id: Modem.ycp 21341 2005-02-07 16:15:59Z mvidner $
 *
 * Representation of the configuration of modem.
 * Input and output routines.
 */

{

module "Modem";
textdomain "network";

import "NetworkDevices";
import "Provider";
import "Progress";
import "Routing";
import "Service";
import "Summary";
import "SuSEFirewall4Network";

include "network/complex.ycp";

/* general stuff */
global string description = "";
global string type = "";
global string device = "";
global string unique = "";
global string startmode = "manual";
global boolean usercontrol = false;
global list<string> Requires = [];

/**
 * Hotplug type ("" if not hot pluggable)
 */
global string hotplug = "";

/* modem settings */
global string Init1 = "ATZ";
global string Init2 = "AT Q0 V1 E1 S0=0 &C1 &D2 +FCLASS=0";
global string Init3 = "";
global integer BaudRate = 57600;

global boolean PulseDial = true;
global boolean Carrier = true;
global boolean Speaker = true;

global string Device = "/dev/modem";
global string DialPrefix = "";
global string DialPrefixRx = "";
global string PPPDoptions = "";

/* something already proposed? */
global boolean proposal_valid = false;

/*--------------*/
/* PRIVATE DATA */

/**
 * Hardware information
 * @see ReadHardware
 */
list<map> Hardware = [];

/**
 * Abort function
 * return boolean return true if abort
 */
global block<boolean> AbortFunction = nil;

/**
 * Data was modified?
 */
boolean modified = false;

/**
 * Which operation is pending?
 */
symbol operation = nil;

/*------------------*/
/* GLOBAL FUNCTIONS */

/**
 * Data was modified?
 * @return true if modified
 */
global define boolean Modified() {
    y2debug("modified=%1",modified);
    return modified;
}

include "network/hardware.ycp";
include "network/routines.ycp";
include "network/runtime.ycp";

/**
 * Read all network settings from the SCR
 * @return true on success
 */
global define boolean Read() {

    /* Read dialog caption */
    string caption = _("Initializing Modem Configuration");
    integer steps = 5;

    integer sl = 0; /* 1000; /* TESTING */
    sleep(sl);

    Progress::New(caption, " ", steps, [
	/* Progress stage 1/4 */
	_("Detect modems"),
	/* Progress stage 2/4 */
	_("Read current configuration"),
	/* Progress stage 3/4 */
	_("Read firewall settings"),
	/* Progress stage 4/4 */
	_("Read providers"),
	/* Progress stage 5/5 */
	_("Read routing"),
    ], [], "");

    if(Abort()) return false;
    /* Progress step 1/4 */
    ProgressNextStage(_("Detecting modems..."));
    Hardware = ReadHardware("modem");
    sleep(sl);

    if(Abort()) return false;
    /* Progress step 2/4 */
    ProgressNextStage(_("Reading current configuration..."));
    NetworkDevices::Read();
    sleep(sl);

    if(Abort()) return false;
    /* Progress step 3/4 */
    ProgressNextStage(_("Reading firewall settings..."));
    boolean progress_orig = Progress::set (false);
    SuSEFirewall4Network::Read ();
    Progress::set (progress_orig);
    sleep(sl);

    if(Abort()) return false;
    /* Progress step 4/4 */
    ProgressNextStage(_("Reading providers..."));
    Provider::Read();
    sleep(sl);

    if(Abort()) return false;
    /* Progress step 4/4 */
    ProgressNextStage(_("Reading routes..."));
    if(!proposal_valid) {
	Routing::Read();
    }
    sleep(sl);

    if(Abort()) return false;
    /* Final progress step */
    ProgressNextStage(_("Finished"));
    sleep(sl);

    if(Abort()) return false;
    modified = false;
    return true;
}

/**
 * Update the SCR according to network settings
 * @return true on success
 */
global define boolean Write() {

    if(!modified && !Provider::Modified("modem")) return true;
    y2milestone("Writing configuration");

    /* Write dialog caption */
    string caption = _("Saving Modem Configuration");
    integer steps = 6;

    integer sl = 0; /* 1000; /* TESTING */
    sleep(sl);

    Progress::New(caption, " ", steps, [
	/* Progress stage 1/6 */
	_("Write configuration"),
	/* Progress stage 2/6 */
	_("Write firewall settings"),
	/* Progress stage 3/6 */
	_("Write providers"),
	/* Progress stage 4/6 */
	_("Set up network services"),
	/* Progress stage 5/5 */
	_("Set up smpppd"),
	/* Progress stage 6/6 */
	_("Run KInternet"),
    ], [], "");

    if(Abort()) return false;
    /* Progress step 1/6 */
    ProgressNextStage(_("Writing configuration..."));
    NetworkDevices::Write("modem");
    NetworkDevices::UpdateModemSymlink();
    sleep(sl);

    if(Abort()) return false;
    /* Progress step 2/6 */
    ProgressNextStage(_("Writing firewall settings..."));
    boolean progress_orig = Progress::set (false);
    SuSEFirewall4Network::Write ();
    Progress::set (progress_orig);
    sleep(sl);

    if(Abort()) return false;
    /* Progress step 3/6 */
    ProgressNextStage(_("Writing providers..."));
    Provider::Write("modem");
    sleep(sl);

    if(Abort()) return false;
    /* Progress step 4/6 */
    ProgressNextStage(_("Setting up network services..."));
    EnableNetwork();
    sleep(sl);

    /* Setup SL modem */
    if(contains(Requires, "smartlink-softmodem")) {

	y2milestone("Setting up smartlink-softmodem ...");

	Service::Stop("slmodemd");

	string country = Provider::GetCountry ();
	map keys = (map) eval(SCR::Read(.target.yast2, "modem-t35-keys.ycp"));
	country = keys[country]:"";

	y2milestone("Setting up slmodemd (%1)", country);
	if(country != nil && country != "") {
	    SCR::Write(.sysconfig.slmodemd.SLMODEMD_COUNTRY, toupper(country));
	    SCR::Write(.sysconfig.slmodemd, nil);
	}

	Service::Enable("slmodemd");
	Service::Start("slmodemd");
    }

    if(Abort()) return false;
    /* Progress step 5/6 */
    ProgressNextStage(_("Setting up smpppd(8)..."));
    SetupSMPPPD();
    sleep(sl);

    if(Abort()) return false;
    /* Progress step 6/6 */
    ProgressNextStage(_("Running KInternet..."));
    RunKInternet();
    sleep(sl);

    if(Abort()) return false;
    /* Final progress step */
    ProgressNextStage(_("Finished"));
    sleep(sl);

    if(Abort()) return false;
    return true;
}

/**
 * Select the given device
 * @param dev device to select ("" for new device, default values)
 * @return true if success
 */
global define boolean Select(string dev) {

    y2debug("dev=%1", dev);
    // defaults for a new device
    map devmap = $[
	"USERCONTROL": "yes",
	];

    /* dev=="" -> Add */
    if(dev == "") {
	type = "modem";
	device = NetworkDevices::GetFreeDevice(type);
    }
    /* dev!="" -> Edit */
    else {
	string typ = NetworkDevices::device_type(dev);
	string num = NetworkDevices::device_num(dev);

	NetworkDevices::Edit(dev);
	devmap = NetworkDevices::Current;

	type = typ;
	device = num;
	// FIXME: why is this here? operation = `edit;
    }

    /* general stuff */
    description = BuildDescription (type, device, devmap, Hardware);
    unique = devmap["UNIQUE"]:"";
    startmode = devmap["STARTMODE"]:"manual";
    usercontrol = devmap["USERCONTROL"]:"no" == "yes";

    /* modem settings */
    Init1 = devmap["INIT1"]:"ATZ";
    Init2 = devmap["INIT2"]:"AT Q0 V1 E1 S0=0 &C1 &D2 +FCLASS=0";
    Init3 = devmap["INIT3"]:"";
    BaudRate = tointeger(devmap["SPEED"]:"57600");

    /* PulseDial = devmap["DIALCOMMAND"]:"ATDT" == "ATDP";
     * better heuristics: */
    PulseDial = filterchars(devmap["DIALCOMMAND"]:"ATDT", "P") == "P";
    Speaker = devmap["INIT8"]:"ATM1" == "ATM1";
    Carrier = devmap["INIT9"]:"" == "";

    Device = devmap["MODEM_DEVICE"]:"/dev/modem";
    DialPrefix = devmap["DIALPREFIX"]:"";
    DialPrefixRx = devmap["DIALPREFIXREGEX"]:"";
    PPPDoptions = devmap["PPPD_OPTIONS"]:"";

    /* provider settings */
    Provider::Name = devmap["PROVIDER"]:"";

    return true;
}

/**
 * Add a new device
 * @return true if success
 */
global define boolean Add() {
    operation = nil;
    if(Select("") != true) return false;
    NetworkDevices::Add();
    operation = `add;
    return true;
}

/**
 * Edit the given device
 * @param name device to edit
 * @return true if success
 */
global define boolean Edit(string name) {
    operation = nil;
    if(Select(name) != true) return false;
    NetworkDevices::Edit(name);
    operation = `edit;
    return true;
}


/**
 * Delete the given device
 * @param name device to delete
 * @return true if success
 */
global define boolean Delete(string name) {
    operation = nil;
    if(Select(name) != true) return false;
    NetworkDevices::Delete(name);
    operation = `delete;
    return true;
}

/**
 * Commit the pending operation
 * @return true if success
 */
global define boolean Commit() {
    y2debug("Commit(%1)",operation);
    if(operation == `add || operation == `edit) {
	map<string,any> newdev = $[
	    "STARTMODE"	: startmode,
	    "USERCONTROL": usercontrol? "yes": "no",
	    "BOOTPROTO"	: "none",
	    "UNIQUE"	: unique,
	    "NAME"	: description,
	    "INIT1"	: Init1,
	    "INIT2"	: Init2,
	    "INIT3"	: Init3,
	    "SPEED"	: sformat("%1", BaudRate),
	    "INIT8"	: Speaker ? "ATM1" : "ATM0",
	    "INIT9"	: Carrier ? "" : "ATX3",
	    "DIALCOMMAND"	: PulseDial ? "ATDP" : "ATDT",
	    "MODEM_DEVICE"	: Device,
	    "DIALPREFIX"	: DialPrefix,
	    "DIALPREFIXREGEX"	: DialPrefixRx,
	    "PROVIDER"		: Provider::Name,
	    // "PROVIDER_NAME"	: Provider::Current["PROVIDER"]:"",
	    "PPPD_OPTIONS"	: PPPDoptions,
	];

	NetworkDevices::Name = NetworkDevices::device_name(type, device);
	NetworkDevices::Current = newdev;
	NetworkDevices::Commit();
    }
    else if(operation == `delete) {
	NetworkDevices::Commit();
    }
    else {
	y2error("Unknown operation: %1", operation);
	return false;
    }

    modified = true;
    operation = nil;
    return true;
}

/**
 * Import data
 * @param settings settings to be imported
 * @return true on success
 */
global define boolean Import(map settings) {
    NetworkDevices::Import("modem", settings["devices"]:$[]);
    Provider::Import("modem", settings["providers"]:$[]);
    return true;
}

/**
 * Export data
 * @return dumped settings (later acceptable by Import())
 */
global define map Export() {
    return $[
	"devices"	: NetworkDevices::Export("modem"),
	"providers"	: Provider::Export("modem"),
    ];
}

/**
 * Create a textual summary and a list of unconfigured devices
 * @param split split configured and unconfigured?
 * @return summary of the current configuration
 */
global define list Summary(boolean split) {
    return BuildSummary("modem", Hardware, split);
}

/**
 * Create an overview table with all configured devices
 * @return table items
 */
global define list Overview() {
    return BuildOverview("modem", Hardware);
}

/**
 * Select the hardware component
 * @param which index of the component
 */
global define void SelectHW(integer which) {
    map sel = SelectHardware(Hardware, which);

    Init1 = sel["init1"]:"";
    Init2 = sel["init2"]:"";
    Device = sel["device_name"]:"";
    BaudRate = sel["speed"]:57600;
    PPPDoptions = sel["pppd_options"]:"";
    type = "modem";
}

global list<string> Packages() {
    if(size(NetworkDevices::List("modem")) < 1) return [];
    return ["smpppd"];
}

/* EOF */
}
