package canaconnect

type Data struct {
	Sessions map[string]string
	Users    map[string]*User
}

func (d *Data) RequestContact(userID, phone string) {
	u, ok := d.Users[phone]
	if !ok {
		return
	}
	if u.Blocks[userID] {
		return
	}
	for _, id := range u.Requests {
		if id == userID {
			return
		}
	}
	for _, id := range u.Contacts {
		if id == userID {
			return
		}
	}
	u.Requests = append([]string{userID}, u.Requests...)
}

func (d *Data) AcceptContact(userID, phone string) {
	u, ok := d.Users[userID]
	if !ok {
		return
	}
	for i, id := range u.Requests {
		if id == phone {
			u.Requests = append(u.Requests[:i], u.Requests[i+1:]...)
			u.Contacts = append([]string{phone}, u.Contacts...)
			d.Users[phone].Contacts = append([]string{userID}, d.Users[phone].Contacts...)
			return
		}
	}
}

func (d *Data) Home(userID string) *Home {
	u, ok := d.Users[userID]
	if !ok {
		return nil
	}
	home := &Home{
		Contacts:    []Contact{},
		Settings:    u.Settings,
		RingFrom:    u.RingFrom,
		ConnectedTo: u.ConnectedTo,
		Calling:     u.Calling,
	}
	for _, id := range u.Requests {
		home.Contacts = append(home.Contacts, struct {
			ID        string `json:"id"`
			Name      string `json:"name"`
			IsRequest bool   `json:"isRequest"`
		}{
			ID:        id,
			Name:      d.Users[id].Settings.DisplayName,
			IsRequest: true,
		})
	}
	for _, id := range u.Contacts {
		home.Contacts = append(home.Contacts, struct {
			ID        string `json:"id"`
			Name      string `json:"name"`
			IsRequest bool   `json:"isRequest"`
		}{
			ID:        id,
			Name:      d.Users[id].Settings.DisplayName,
			IsRequest: false,
		})
	}
	return home
}

func (d *Data) GetContacts(userID string) []string {
	contacts := []string{}
	for id, u := range d.Users {
		for _, c := range u.Contacts {
			if c == userID {
				contacts = append(contacts, id)
			}
		}
		for _, c := range u.Requests {
			if c == userID {
				contacts = append(contacts, id)
			}
		}
		for c := range u.Blocks {
			if c == userID {
				contacts = append(contacts, id)
			}
		}
	}
	return contacts
}

type Home struct {
	Contacts    []Contact `json:"contacts"`
	Settings    *Settings `json:"settings"`
	ConnectedTo string    `json:"connectedTo"`
	RingFrom    string    `json:"ringFrom"`
	Calling     string    `json:"calling"`
}

type Contact struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	IsRequest bool   `json:"isRequest"`
}

type User struct {
	LoginCodes  map[string]bool
	Settings    *Settings
	Contacts    []string
	Requests    []string
	Blocks      map[string]bool
	ConnectedTo string
	RingFrom    string
	Calling     string
	Description []byte
	Candidates  [][]byte
}

func (d *Data) Connections(userID string) []string {
	res := []string{}
	for id, u := range d.Users {
		if id == userID {
			continue
		}
		found := false
		for _, c := range u.Contacts {
			if c == userID {
				res = append(res, id)
				found = true
				break
			}
		}
		if found {
			continue
		}
		for _, c := range u.Requests {
			if c == userID {
				res = append(res, id)
				found = true
				break
			}
		}
		if found {
			continue
		}
		for c := range u.Blocks {
			if c == userID {
				res = append(res, id)
				break
			}
		}
	}
	return res
}

func (u *User) HasRequested(phone string) bool {
	for _, id := range u.Requests {
		if id == phone {
			return true
		}
	}
	return false
}

func (u *User) DeleteRequest(phone string) {
	i := -1
	for j, id := range u.Requests {
		if id == phone {
			i = j
			break
		}
	}
	if i == -1 {
		return
	}
	u.Requests = append(u.Requests[:i], u.Requests[i+1:]...)
}

func (u *User) IsBlocked(phone string) bool {
	return u.Blocks[phone]
}

func (u *User) IsContact(phone string) bool {
	for _, id := range u.Contacts {
		if id == phone {
			return true
		}
	}
	return false
}

type Settings struct {
	DisplayName            string `json:"displayName"`
	DisplayNameLastUpdated int64  `json:"displayNameLastUpdated"`
}
