package main

import (
	"fmt"
	"log"
	"math/rand"
	"strings"
	"time"

	"xeserv.us/r1459"

	"gopkg.in/telegram-bot-api.v4"
)

type Room struct {
	ID           int
	RoomID       int64 `storm:"index" storm:"unique"`
	Title        string
	Shortname    string `storm:"index" storm:"unique"`
	CreationDate time.Time

	Members []string

	client *Client
}

func (c *Client) MakeRoom(shortname string, roomID int64) (*Room, error) {
	room := &Room{}
	err := c.DB.One("RoomID", roomID, room)
	if err != nil {
		chat, err := c.TGBot.GetChat(tgbotapi.ChatConfig{
			ChatID: roomID,
		})
		if err != nil {
			return nil, err
		}

		room = &Room{
			ID:           rand.Int(),
			RoomID:       roomID,
			Title:        chat.Title,
			Shortname:    shortname,
			CreationDate: time.Now(),
			Members:      []string{},
		}

		admins, err := c.TGBot.GetChatAdministrators(tgbotapi.ChatConfig{
			ChatID: roomID,
		})

		var nicks []string

		for _, admin := range admins {
			var status string
			if admin.IsCreator() {
				status = "~"
			} else {
				status = "&"
			}
			nicks = append(nicks, status+admin.User.UserName)
		}

		nicks = append(nicks, c.Nick)

		room.Members = append(room.Members, nicks...)

		c.DB.Save(room)
	}

	room.client = c

	return room, nil
}

func (r *Room) Burst() []*r1459.RawLine {
	ret := []*r1459.RawLine{}
	c := r.client

	ret = append(ret, &r1459.RawLine{
		Verb:   "JOIN",
		Source: Mask(c.Nick),
		Args: []string{
			fmt.Sprintf("#%v", r.Shortname),
		},
	})

	ret = append(ret, &r1459.RawLine{
		Verb:   "MODE",
		Source: "xeserv.us",
		Args: []string{
			fmt.Sprintf("#%v", r.Shortname),
			"+nt",
		},
	})

	ret = append(ret, &r1459.RawLine{
		Verb:   "TOPIC",
		Source: "xeserv.us",
		Args: []string{
			fmt.Sprintf("#%v", r.Shortname),
			r.Title,
		},
	})

	ret = append(ret, &r1459.RawLine{
		Verb:   "353",
		Source: "xeserv.us",
		Args: []string{
			c.Nick, "=", fmt.Sprintf("#%v", r.Shortname),
			strings.Join(r.Members, " "),
		},
	})

	ret = append(ret, &r1459.RawLine{
		Verb:   "366",
		Source: "xeserv.us",
		Args: []string{
			c.Nick, fmt.Sprintf("#%v", r.Shortname),
			"End of /NAMES list",
		},
	})

	return ret
}

func (r Room) RecieveMessage(update tgbotapi.Update) {
	c := r.client

	log.Printf("[#%v] %s %s", r.Shortname, update.Message.From.UserName, update.Message.Text)

	found := false
	for _, member := range r.Members {
		if member == "" {
			continue
		}
		if update.Message.From.UserName == member[1:] || update.Message.From.UserName == member {
			found = true
		}
	}

	if !found {
		r.Members = append(r.Members, update.Message.From.UserName)
		c.DB.Save(&r)

		c.SendLine(&r1459.RawLine{
			Verb:   "JOIN",
			Source: Mask(update.Message.From.UserName),
			Args: []string{
				"#" + r.Shortname,
			},
		})
	}

	for _, msgLine := range strings.Split(update.Message.Text, " ") {
		c.SendLine(&r1459.RawLine{
			Verb:   "PRIVMSG",
			Source: Mask(update.Message.From.UserName),
			Args: []string{
				"#" + r.Shortname,
				msgLine,
			},
		})
	}
}

func (r Room) SendMessage(l *r1459.RawLine) error {
	msg := tgbotapi.NewMessage(r.RoomID, l.Args[1])
	_, err := r.client.TGBot.Send(msg)
	return err
}
