/*
Copyright (C) 2005 David Green <green@couchpotato.net>
All Rights Reserved.

This file is part of Aelfengard.

Aelfengard is proprietary software. You may not redistribute it without
prior written permission from the copyright holder.
*/

package server.token;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import server.ContainerHolder;
import server.Item;
import server.Living;
import server.Player;
import server.RoomEntity;

class ComparePart extends Part {

    private final TokenString choiceIfMatch;
    private final TokenString choiceIfNoMatch;
    private final Set<Integer> indexes;
    private final boolean compareOwner;
    
    public ComparePart(boolean capitalize, int idx, Set<Integer> indexes, TokenString choiceIfMatch, TokenString choiceIfNoMatch, boolean compareOwner) {
        super(Type.ENTITY, idx, capitalize);
        this.indexes = Collections.unmodifiableSet(indexes);
        this.choiceIfMatch = choiceIfMatch;
        this.choiceIfNoMatch = choiceIfNoMatch;
        this.compareOwner = compareOwner;
    }
    
    @Override
    public ResolvedPart apply(Player observer, boolean somebodyIfUnknown, String[] strings, RoomEntity... entities) {
        ResolvedTokenString matchRTS = choiceIfMatch.resolve(false, observer, somebodyIfUnknown, strings, entities);
        ResolvedTokenString noMatchRTS = choiceIfNoMatch.resolve(false, observer, somebodyIfUnknown, strings, entities);
        return new CompareResolvedPart(matchRTS, noMatchRTS);
    }
    
    private class CompareResolvedPart extends ResolvedPart {

        private final ResolvedTokenString matchRTS;
        private final ResolvedTokenString noMatchRTS;
        
        public CompareResolvedPart(ResolvedTokenString matchRTS, ResolvedTokenString noMatchRTS) {
            this.matchRTS = matchRTS;
            this.noMatchRTS = noMatchRTS;
        }

        @Override
        public void add(ResolvedPart part) {
            // Nothing to do
        }
        
        @Override
        public String toString(Player observer, boolean somebodyIfUnknown, List<Set<String>> strings, List<Set<RoomEntity>> entities) {
            Set<RoomEntity> source = getSet(observer, entities, getIdx());
            if (compareOwner) {
                Set<RoomEntity> owners = new HashSet<RoomEntity>();
                for (RoomEntity entity : source) {
                    if (!(entity instanceof Item)) {
                        return noMatchRTS.toString();
                    }
                    Item item = (Item) entity;
                    ContainerHolder holder = item.getContainer().getHolder();
                    if (!(holder instanceof Living)) {
                        return noMatchRTS.toString();
                    }
                    Living living = (Living) holder;
                    owners.add(living);
                }
                source = owners; // compare to owners instead of original items
            }
            boolean matches = false;
            for (int idx : indexes) {
                Set<RoomEntity> target = getSet(observer, entities, idx);
                if (target.equals(source)) {
                    matches = true;
                    break;
                }
            }
            if (matches) {
                return matchRTS.toString();
            }
            else {
                return noMatchRTS.toString();
            }
        }
        
    }
    
    private static Set<RoomEntity> getSet(Player observer, List<Set<RoomEntity>> entities, int idx) {
        if (idx != 0) {
            if (idx > entities.size()) {
                return Collections.emptySet();
            }
            return entities.get(idx - 1);
        }
        Set<RoomEntity> ret = new HashSet<RoomEntity>();
        ret.add(observer);
        return ret;
    }
    
}