package services import ( lucifer3 "git.aiterp.net/lucifer3/server" "git.aiterp.net/lucifer3/server/commands" "git.aiterp.net/lucifer3/server/events" "git.aiterp.net/lucifer3/server/internal/gentools" "reflect" "strings" ) func Resolver() lucifer3.Service { return &resolver{ tags: make(map[string][]string), names: make(map[string][]string), } } type resolver struct { tags map[string][]string names map[string][]string } func (r *resolver) Active() bool { return true } func (r *resolver) HandleEvent(_ *lucifer3.EventBus, event lucifer3.Event) { switch event := event.(type) { case events.HardwareState: // On HardwareState, use the internal name if (and only if) it is not already named. if event.InternalName != "" { found := false for _, ids := range r.names { i := gentools.IndexOf(ids, event.ID) if i != -1 { found = true break } } if !found { r.names[event.InternalName] = append(r.names[event.InternalName], event.ID) } } } } func (r *resolver) rerun(bus *lucifer3.EventBus, resolveList *[]string, command interface{}) { newList := make([]string, 0, 16) for _, id := range *resolveList { switch { case strings.HasPrefix(id, "lucifer:tag:"): tag := id[12:] if len(newList) == 0 { newList = append(newList, r.tags[tag]...) } else { gentools.AddUniques(&newList, r.tags[tag]...) } case strings.HasPrefix(id, "lucifer:name:"): name := id[13:] if strings.HasSuffix(name, "*") { prefix := name[:len(name)-1] for name, ids := range r.names { if strings.HasPrefix(name, prefix) { gentools.AddUniques(&newList, ids...) } } } else if strings.HasPrefix(name, "*") { suffix := name[1:] for name, ids := range r.names { if strings.HasSuffix(name, suffix) { gentools.AddUniques(&newList, ids...) } } } else { gentools.AddUniques(&newList, r.names[name]...) } } } if len(newList) > 0 { *resolveList = newList bus.RunCommand(reflect.Indirect(reflect.ValueOf(command)).Interface().(lucifer3.Command)) } } func (r *resolver) HandleCommand(bus *lucifer3.EventBus, command lucifer3.Command) { switch command := command.(type) { case commands.Assign: r.rerun(bus, &command.IDs, &command) case commands.ReplaceScene: r.rerun(bus, &command.IDs, &command) case commands.ClearScene: r.rerun(bus, &command.IDs, &command) case commands.SetName: if !strings.HasPrefix(command.ID, "lucifer:") { for name := range r.names { i := gentools.IndexOf(r.names[name], command.ID) if i != -1 { r.names[name] = append(r.names[name][:i], r.names[name][i+1:]...) } } r.names[command.Name] = append(r.names[command.Name], command.ID) } case commands.AddTag: for _, id := range command.IDs { if strings.HasPrefix(id, "lucifer:") { continue } found := false for _, id2 := range r.tags[command.Tag] { if id == id2 { found = true break } } if !found { r.tags[command.Tag] = append(r.tags[command.Tag], id) } } r.rerun(bus, &command.IDs, &command) case commands.RemoveTag: for _, id := range command.IDs { if strings.HasPrefix(id, "lucifer:") { continue } for i, id2 := range r.tags[command.Tag] { if id == id2 { r.tags[command.Tag] = append(r.tags[command.Tag][:i], r.tags[command.Tag][i+1:]...) break } } } r.rerun(bus, &command.IDs, &command) } }