#!/usr/local/bin/perl
#
# A perl script to connect to the 'weather server' at
# Michigan and get the forcast for whatever city
# you want (3 letter code -- columbus 'cmh' by default).
#
# Alternatively, you can get the current information for
# a state if you enter a 2 letter code.
#
# Thanks to J Greely for the original network code, and
# Tom Fine for assistance and harassment.
#
# Copyright 1991 Frank Adelstein.  All Rights Reserved.
#
# Permission to use, copy, modify, and distribute this
# software is hereby granted without fee, provided that
# the copyright notice and permission notice are not removed.
#
# --FNA 6/28/91
#
# Hacked by George Ferguson (ferguson@cs.rochester.edu) to include
# Canadian forecasts by zone number.
#
# Modified by gf for new weather service menus, 26 Jun 1992.
# I ripped lots of stuff out of this version, some of it may have to be
# put back, but it works fine for me.
# It's much easier to navigate the system now (for US forecasts, anyway),
# so the interaction loop is considerably simplified. The Canadian stuff
# is relatively straightforward also.
#

$SERVER = "downwind.sprl.umich.edu";
$PORT   = "3000";

#
# Parse argument, if any
#
$CITY = $ARGV[0]; 
if ($CITY eq "") {
    $CITY = "cmh";		# No arg -> use default city
}

#
# Allow 4-char symbolic names for Canadian reports.
#
%canNames = ("salt","1",  "SALT","1",
	     "calt","2",  "CALT","2",
	     "nalt","3",  "NALT","3", "nebc","3", "NEBC","3",
	     "cobc","4",  "COBC","4",
	     "inbc","5",  "INBC","5",
	     "sman","6",  "SMAN","6",
	     "nman","7",  "NMAN","7",
	     "nova","8",  "NOVA","8",
	     "pedi","9",  "PEDI","9",
	     "newb","10", "NEWB","10",
	     "labr","11", "LABR","11",
	     "nfld","12", "NFLD","12",
	     "sont","13", "SONT","13",
	     "nont","14", "NONT","14",
	     "nwon","15", "NWON","15",
	     "ssas","16", "SSAS","16",
	     "nsas","17", "NSAS","17",
	     "yukn","18", "YUKN","18",
	     "sque","19", "SQUE","19", "ottw","19", "OTTW","19",
	     "nque","20", "NQUE","20");              
#
# If we're given one of these names, use the number instead.
#
if ($t=$canNames{$CITY}) {
    $CITY = $t;
}

#
# Check argument
#
if ($CITY =~ /[0-9]+/) {
    $ISCAN = 1;
} elsif (length ($CITY) == 3 ) {
    $ISCAN = 0;
} elsif (length ($CITY) == 2 ) {
    $ISCAN = 0;
} else {
    print "Must be either a 2 letter state code or 3 letter city code.\n";
    print "Can also be a numeric Canadian zone number or symbolic name.\n";
    exit (1);
}

#
# Connect to the server
#
local($sockaddr,$here,$there,$response,$tries) = ("Snc4x8");
$here  = pack($sockaddr,2,0,&getaddress("localhost"));
$there = pack($sockaddr,2,$PORT,&getaddress($SERVER));
print "\nConnecting to $SERVER.";
die "socket: $!\n" if (!socket(SOCK,2,1,6));
print ".";
die "connect: $!\n" if (!connect(SOCK,$there));
print ".connected\n";
select(SOCK); $| = 1;
select(STDOUT); $| = 1;       # make unbuffered

#
# Initialize
#
$SHOWIT = 0;			# Should we print?
$MAINMENU = 0;			# Seen main menu once already?
$CANMENU = 0;			# See Canadian menu once already?

#
# Interact...
#
while (read(SOCK,$c,1)) {	# Get a character
    if ($c eq "\n") {		# Newline -> maybe print, start new line
	if ($SHOWIT == 1) {
	    print $curline, "\n";
	}
	$curline = "";
	next; 
    }
    if ($c eq "\r") { next; }	# Return -> ignore
    $curline .= $c;		# Else add char to current line
	
    #
    # Now test the current line so far to see what action to take, if any.
    #
    if ($curline =~ /Press Return for menu, or enter 3 letter forecast city code:/) { # At first prompt...
	if ($ISCAN) {
	    printf SOCK "\n";	# For Canadian forecast, go via main menu
	} else {
	    printf SOCK "%s\n", $CITY; # For US, bypass menu
	    $curline = "";
	    &showiton("us city/state");
	}
    } elsif ($curline =~ / Selection:/) { # In main menu...
	if ($ISCAN) {		# Canadian forecast...
	    if (!$MAINMENU) {	    # At main menu, select Canadian forecasts
		$MAINMENU = 1;
		printf SOCK "2\n";  # Canadian forecast is item 2!!
		$curline = "";
	    } elsif (!$CANMENU) {   # At Canadian menu, select region
		$CANMENU = 1;
		printf SOCK "%s\n", $CITY;
		&showiton("canadian region");
		$curline = "";
	    } else {
		printf SOCK "X\n";  # Otherwise exit
	    }
	} else {
	    printf SOCK "X\n";	# Otherwise exit
	}
    } elsif ($curline =~ / Invalid 3-letter city code./) {
	printf SOCK "X\n";
	printf "%s is an invalid 3 letter city code.\n", $CITY;
	&showitoff("3-letter");
    } elsif ($curline =~ / Invalid city or state code./) {
	printf SOCK "X\n";
	printf "%s is an invalid city or state code.\n", $CITY;
	&showitoff("invalid");
    } elsif ($curline =~ / CITY FORECAST MENU/) {
	&showitoff("city forecast");
    } elsif ($curline =~ / CURRENT WEATHER MENU/) {
	&showitoff("city forecast");
    } elsif ($curline =~ / CANADIAN FORECASTS/) {
	&showitoff("canadian forecasts");
    } elsif ($curline =~ / Press Return to continue: /) {
	printf SOCK "\n";
	$curline = "";
	&showiton("Return to continue");
    } elsif ($curline =~ / Press Return to continue printing or M to return to menu: /) {
	printf SOCK "\n";
	$curline = "";
	&showiton("Return to continue printing");
    }
}

#
# Clean up and done
#
close(SOCK);
exit(0);

#####################################################

sub getaddress {
    local($host) = @_;
    local(@ary);
    @ary = gethostbyname($host);
    return(unpack("C4",$ary[4]));
}

sub showitoff {
    local($txt) = @_;
    &maybeprint ("showit off ($txt)\n");
    $SHOWIT = 0;
}

sub showiton {
    local($txt) = @_;
    &maybeprint ("showit on ($txt)\n");
    $SHOWIT = 1;
}

sub maybeprint {
#    print @_;
}
