package main

import (
	"bytes"
	"context"
	"encoding/xml"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strings"

	"github.com/golang/glog"
)

type Envelope struct {
	XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Envelope"`
	Body    *Body
}

type Body struct {
	XMLName  xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Body"`
	Request  *Request
	Response *Response
	Fault    *Fault
}

type Request struct {
	XMLName xml.Name `xml:"urn:AC executeCommand"`
	Command string   `xml:"command"`
}
type Response struct {
	XMLName xml.Name `xml:"urn:AC executeCommandResponse"`
	Result  string   `xml:"result"`
}

type Fault struct {
	XMLName xml.Name `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault"`
	Code    string   `xml:"faultcode"`
	String  string   `xml:"faultstring"`
}

type commandRes struct {
	result string
	fault  string
}

var (
	reAccount  = regexp.MustCompile(`^[a-z0-9\-_\.]{3,16}$`)
	rePassword = regexp.MustCompile(`^[a-zA-Z0-9\-_\.]{3,16}$`)
)

func createAccount(ctx context.Context, name, password string) error {
	if !reAccount.MatchString(name) {
		return fmt.Errorf("invalid account name")
	}
	if !rePassword.MatchString(password) {
		return fmt.Errorf("invalid password name")
	}
	res, err := runCommand(ctx, fmt.Sprintf("account create %s %s", name, password))
	if err != nil {
		glog.Errorf("Account create: %v", err)
		return fmt.Errorf("server unavailable")
	}
	if res.result == fmt.Sprintf("Account created: %s", name) {
		glog.Infof("Created account %q", name)
		return nil
	}
	glog.Errorf("Account create fault: %q/%q", res.fault, res.result)
	return fmt.Errorf("server error")
}

func ensureAccount(ctx context.Context, name, password string) error {
	if !reAccount.MatchString(name) {
		return fmt.Errorf("invalid account name")
	}
	if !rePassword.MatchString(password) {
		return fmt.Errorf("invalid password name")
	}
	res, err := runCommand(ctx, fmt.Sprintf("account create %s %s", name, password))
	if err != nil {
		glog.Errorf("Account create: %v", err)
		return fmt.Errorf("server unavailable")
	}
	if res.result == fmt.Sprintf("Account created: %s", name) {
		glog.Infof("Created account %q", name)
		return nil
	}
	if res.fault != "Account with this name already exist!" {
		glog.Errorf("Account create fault: %q/%q", res.fault, res.result)
		return fmt.Errorf("server error")
	}

	res, err = runCommand(ctx, fmt.Sprintf("account set password %s %s %s", name, password, password))
	if res.result == "The password was changed" {
		glog.Infof("Updated password for account %q", name)
		return nil
	}
	glog.Infof("password update fault: %q/%q", res.fault, res.result)
	return fmt.Errorf("server error")
}

func runCommand(ctx context.Context, cmd string) (*commandRes, error) {
	data, err := xml.Marshal(&Envelope{
		Body: &Body{
			Request: &Request{
				Command: cmd,
			},
		},
	})
	if err != nil {
		return nil, fmt.Errorf("marshal: %w", err)
	}
	buf := bytes.NewBuffer(data)
	req, err := http.NewRequestWithContext(ctx, "POST", flagSOAPAddress, buf)
	if err != nil {
		return nil, fmt.Errorf("NewRequest(POST, %q): %w", flagSOAPAddress, err)
	}

	req.SetBasicAuth(flagSOAPUsername, flagSOAPPassword)
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		return nil, fmt.Errorf("req.Do: %w", err)
	}
	defer resp.Body.Close()

	respBytes, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("ReadAll response: %w", err)
	}

	respEnvelope := Envelope{}
	err = xml.Unmarshal(respBytes, &respEnvelope)
	if err != nil {
		return nil, fmt.Errorf("unmarshal: %w", err)
	}

	if respEnvelope.Body == nil {
		return nil, fmt.Errorf("no body returned")
	}

	if respEnvelope.Body.Fault != nil {
		fault := respEnvelope.Body.Fault
		if fault.Code == "SOAP-ENV:Client" {
			return &commandRes{
				fault: strings.TrimSpace(fault.String),
			}, nil
		}
		return nil, fmt.Errorf("SOAP error %q: %v", fault.Code, fault.String)
	}

	result := ""
	if respEnvelope.Body.Response != nil {
		result = respEnvelope.Body.Response.Result
	}

	return &commandRes{
		result: strings.TrimSpace(result),
	}, nil
}

type playerinfo struct {
	Account   string
	Character string
}

func onlinelist(ctx context.Context) ([]playerinfo, error) {
	res, err := runCommand(ctx, "account onlinelist")
	if err != nil {
		glog.Errorf("onlinelist: %v", err)
		return nil, fmt.Errorf("server unavailable")
	}
	if res.fault != "" {
		glog.Errorf("onlinelist fault: %q", res.fault)
		return nil, fmt.Errorf("server unavailable")
	}

	lines := strings.Split(res.result, "\n")
	header := false
	var pi []playerinfo
	for _, line := range lines {
		switch {
		case strings.HasPrefix(line, "-="):
			continue
		case strings.HasPrefix(line, "-["):
		default:
			glog.Warningf("unparseable line %q", line)
			continue
		}
		if !header {
			header = true
			continue
		}
		if len(line) != 69 {
			glog.Warningf("wrong line length: %q", line)
			continue
		}
		account := strings.ToLower(strings.TrimSpace(line[2:18]))
		if line[18:20] != "][" {
			glog.Warningf("unparseable line %q (wrong sep1)", line)
			continue
		}
		character := strings.TrimSpace(line[20:32])
		if line[32:34] != "][" {
			glog.Warningf("unparseable line %q (wrong sep2)", line)
			continue
		}
		pi = append(pi, playerinfo{
			Account:   account,
			Character: character,
		})
	}
	glog.Infof("Onlinelist: %v", pi)
	return pi, nil
}
