package door

import (
	"bufio"
	"log"
	"os"
	"path"
	"strconv"
	"strings"
	"time"
)

/*
https://github.com/NuSkooler/ansi-bbs/blob/master/docs/dropfile_formats/door32_sys.txt

door32.sys:

0				Line 1 : Comm type (0=local, 1=serial, 2=telnet)
0				Line 2 : Comm or socket handle
38400			Line 3 : Baud rate
Mystic 1.07		Line 4 : BBSID (software name and version)
1				Line 5 : User record position (1-based)
James Coyle		Line 6 : User's real name
g00r00			Line 7 : User's handle/alias
255				Line 8 : User's security level
58				Line 9 : User's time left (in minutes)
1				Line 10: Emulation *(See below)
1				Line 11: Current node number

Emulation:
 0 = Ascii
 1 = Ansi
 2 = Avatar
 3 = RIP
 4 = Max Graphics

http://wiki.synchro.net/ref:door.sys

door.sys:

Line #	Example 		Description 	Comment
1 		COM1: 			Comm Port 		COM0: = LOCAL MODE
2 		2400 			Baud (DCE) Rate	300 to 38400
3 		8 				Parity 			7 or 8
4 		1 				Node Number 	1 to 99
5 		19200 			DTE Rate 		Was Y/N (LOCKED at 19200)
6 		Y 				Screen Display 	Y=On N=Off
7 		Y 				Printer Toggle 	Y=On N=Off
8 		Y 				Page Bell 		Y=On N=Off
9 		Y 				Caller Alarm 	Y=On N=Off
10 		Rick Greer 		User Full Name
11 		Lewisville, Tx. Calling From
12 		214 221-7814 	Home Phone
13 		214 221-7814 	Work/Data Phone
14 		PASSWORD 		Password
15 		110 			Security Level
16 		1456 			Total Times On 	0 through 32767
17 		03/14/88 		Last Date Called 	mm/dd/yy
18 		7560 			Seconds Remaining 	THIS call
19 		126 			Minutes Remaining 	THIS call
20 		GR 				Graphics Mode 	GR=Graph, NG=Non-Graph, 7E=7,E Caller
21 		23 				Page Length 	rows of text
22 		Y 				User Mode 	Y = Expert, N = Novice
23 		1234567 		Conferences/Forums Registered In 	ABCDEFG
24 		7 				Conference Exited To DOOR From 	G
25 		01/01/99 		User Expiration Date 	mm/dd/yy
26 		1 				User File's Record Number 	1+
27 		Y 				Default Protocol 	X, C, Y, G, I, N, Etc.
28 		0 				Total Uploads
29 		0 				Total Downloads
30 		0 				Daily Download “K” Total
31 		999999 			Daily Download Max. “K” Limit
32 		10/22/88 		Caller's Birthdate 	mm/dd/yy
33 		G:\GAP\MAIN 	Path to the MAIN directory 	where user file is
34 		G:\GAP\GEN 		Path to the GEN directory
35 		Michael 		Sysop's Name 	name BBS refers to Sysop as
36 		Stud 			Alias name 	user's alias or handle
37 		00:05 			Event time 	hh:mm
38 		Y 				Error correcting connection 	Y/N
39 		N 				ANSI supported & caller using NG mode 	Y/N
40 		Y 				Use Record Locking 	Y/N
41 		14 				BBS Default Color 	CGA color code (1-15)
42 		10 				Time Credits in Minutes 	-32768 through 32767
43 		07/07/90 		Last New File Scan Date 	mm/dd/yy
44 		14:32 			Time of This Call 	hh:mm
45 		07:30 			Time of Last Call 	hh:mm
46 		6 				Maximum daily files available
47 		3 				Files d/led so far today
48 		23456 			Total “K” Bytes Uploaded
49 		76329 			Total “K” Bytes Downloaded
50 		A File Sucker 	User Comment
51 		10 				Total Doors Opened
52 		10283 			Total Messages Left 	0 through 32767
*/

// DropFile Information
type DropfileConfig struct {
	Comm_type      int    // Comm type (0 local, 2 telnet "linux fd")
	Comm_handle    int    // Handle to use to talk to the user
	BBSID          string // BBS Software name
	User_number    int    // User number
	Real_name      string // User's Real Name
	Handle         string // User's Handle/Nick
	Security_level int    // Security Level (if given)
	Time_left      int    // Time Left (minutes)
	Node           int    // BBS Node number
}

// Read the BBS door file.  We only support door32.sys.
func (d *Door) ReadDropfile(filename string) {
	var file *os.File
	var err error
	var base string = strings.ToLower(path.Base(filename))
	var isDoor32, isDoorSys bool

	if strings.Contains(base, "door.sys") {
		isDoorSys = true
	} else if strings.Contains(base, "door32.sys") {
		isDoor32 = true
	} else {
		log.Panicf("Unknown dropfile format: %s\n", base)
	}

	file, err = os.Open(filename)
	if err != nil {
		log.Panicf("Open(%s): %s\n", filename, err)
	}

	defer file.Close()

	var lines []string
	// read line by line
	// The scanner handles DOS and linux file endings.

	var scanner *bufio.Scanner = bufio.NewScanner(file)
	for scanner.Scan() {
		line := scanner.Text()
		lines = append(lines, line)
	}

	if isDoor32 {
		// door32.sys:
		// 0                            Line 1 : Comm type (0=local, 1=serial, 2=telnet)
		// 0                            Line 2 : Comm or socket handle
		// Mystic 1.07                  Line 4 : BBSID (software name and version)
		// 1                            Line 5 : User record position (1-based)
		// James Coyle                  Line 6 : User's real name
		// g00r00                       Line 7 : User's handle/alias
		// 255                          Line 8 : User's security level
		// 58                           Line 9 : User's time left (in minutes)
		// 1                            Line 11: Current node number

		d.Config.Comm_type, err = strconv.Atoi(lines[0])
		if err != nil {
			log.Panicf("Door32 Comm Type (expected integer): %s\n", err)
		}
		d.Config.Comm_handle, err = strconv.Atoi(lines[1])
		if err != nil {
			log.Panicf("Door32 Comm Handle (expected integer): %s\n", err)
		}
		d.Config.BBSID = lines[3]
		d.Config.User_number, err = strconv.Atoi(lines[4])
		if err != nil {
			log.Panicf("Door32 User Number (expected integer): %s\n", err)
		}
		d.Config.Real_name = lines[5]
		d.Config.Handle = lines[6]
		d.Config.Security_level, err = strconv.Atoi(lines[7])
		if err != nil {
			log.Panicf("Door32 Security Level (expected integer): %s\n", err)
		}
		d.Config.Time_left, err = strconv.Atoi(lines[8])
		if err != nil {
			log.Panicf("Door32 Time Left (expected integer): %s\n", err)
		}
		d.Config.Node, err = strconv.Atoi(lines[10])
		if err != nil {
			log.Panicf("Door32 Node Number (expected integer): %s\n", err)
		}
	} else if isDoorSys {
		// Door.sys:
		// Line 1:	COM1:			Comm Port, COM0: = LOCAL MODE
		// Line 4:	1 				Node Number
		// Line 10:	Rick Greer 		User Full Name
		// Line 11:	Lewisville, Tx.	Calling From
		// Line 15:	110				Security Level
		// Line 18:	7560			Seconds Remaining
		// Line 19:	126				Minutes Remaining
		// Line 26:	1				User File's Record Number
		// Line 35:	Michael			Sysop's Name
		// Line 36:	Stud			Alias name
		if lines[0] == "COM0:" {
			d.Config.Comm_type = 0
		}
		d.Config.Node, err = strconv.Atoi(lines[3])
		if err != nil {
			log.Panicf("Door.sys Node Number (expected integer): %s\n", err)
		}
		d.Config.Real_name = lines[9]
		d.Config.User_number, err = strconv.Atoi(lines[25])
		if err != nil {
			log.Panicf("Door.sys User Number (expected integer): %s\n", err)
		}
		d.Config.Handle = lines[35]
		d.Config.Security_level, err = strconv.Atoi(lines[14])
		if err != nil {
			log.Panicf("Door.sys Security Level (expected integer): %s\n", err)
		}
		d.Config.Time_left, err = strconv.Atoi(lines[18])
		if err != nil {
			log.Panicf("Door.sys Time Left (expected integer): %s\n", err)
		}
	}

	if d.Config.Comm_type == 0 {
		d.READFD = 0
		d.WRITEFD = 1
	} else if d.Config.Comm_type == 2 {
		d.READFD = d.Config.Comm_handle
		d.WRITEFD = d.Config.Comm_handle
	} else {
		log.Panicf("Unsupported Comm type %d\n", d.Config.Comm_type)
	}

	d.StartTime = time.Now()
	// Calculate when time expires.
	d.TimeOut = time.Now().Add(time.Duration(d.Config.Time_left) * time.Minute)
}