package com.indoqa.daisy.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.indoqa.daisy.dao.BinaryDocumentDao;
import com.indoqa.daisy.dao.ContentDocumentDao;
import com.indoqa.daisy.dao.NavigationDao;
import com.indoqa.daisy.entity.BinaryDocument;
import com.indoqa.daisy.entity.ContentDocument;
import com.indoqa.daisy.entity.Navigation;
import com.indoqa.daisy.entity.NavigationElement;
import com.indoqa.daisy.service.ContentService;

@Service
public class ContentServiceImpl implements ContentService {

    @Autowired
    private ContentDocumentDao contentDocumentDao;

    @Autowired
    private NavigationDao navigationDao;

    @Autowired
    private BinaryDocumentDao binaryDocumentDao;

    @Override
    public List<ContentDocument> find(String query, Locale locale) {
        List<String> docIds = this.contentDocumentDao.find(query, locale);

        List<ContentDocument> results = new ArrayList<ContentDocument>();
        for (String documentId : docIds) {
            results.add(this.getContentDocument(documentId, locale, "", null));
        }

        return results;
    }

    @Override
    public BinaryDocument getBinaryDocument(String id, String partType, String fileName, Locale locale) {
        return this.binaryDocumentDao.get(id, locale, partType, fileName);
    }

    @Override
    public ContentDocument getContentDocumentById(String id, String relativizer, Locale locale) {
        Navigation navigation = this.getNavigation(locale);

        // check if the document exists
        NavigationElement navigationElement = navigation.getNavigationElementByDocumentId(id);
        if (navigationElement == null || StringUtils.isEmpty(navigationElement.getDocumentId())) {
            return null;
        }

        Map<String, String> linkTranslationMap = navigation.getLinkTranslationMap();
        return this.getContentDocument(id, locale, relativizer, linkTranslationMap);
    }

    @Override
    public ContentDocument getContentDocumentByPath(String path, Locale locale) {
        Navigation navigation = this.getNavigation(locale);

        NavigationElement navigationElement = navigation.getNavigationElementByPath(path);
        if (navigationElement == null || StringUtils.isEmpty(navigationElement.getDocumentId())) {
            return null;
        }

        Map<String, String> linkTranslationMap = navigation.getLinkTranslationMap();
        return this.getContentDocument(navigationElement.getDocumentId(), locale, createRelativizer(path), linkTranslationMap);
    }

    @Override
    public NavigationElement[] getMenuNavigationElementsForPath(String path, Locale locale) {
        NavigationElement currentElement = this.getNavigation(locale).getNavigationElementByPath(path);

        // navigate to the element one above the root element
        while (currentElement.getParent() != null && !currentElement.getParent().isRoot()) {
            currentElement = currentElement.getParent();
        }

        // add the navigation element at the first level and its children
        List<NavigationElement> elements = new ArrayList<NavigationElement>();
        if (StringUtils.isNotBlank(currentElement.getDocumentId())) {
            elements.add(currentElement);
        }
        for (NavigationElement currentChildElement : currentElement.getChildren()) {
            if (StringUtils.isNotBlank(currentChildElement.getDocumentId())) {
                elements.add(currentChildElement);
            }
        }

        return elements.toArray(new NavigationElement[elements.size()]);
    }

    private ContentDocument getContentDocument(String documentId, Locale locale, String pathRelativizer,
            Map<String, String> linkRewriteTranslationTable) {
        ContentDocument contentDocument = this.contentDocumentDao
                .get(documentId, locale, pathRelativizer, linkRewriteTranslationTable);

        // add the navigation path to the content document
        NavigationElement navEl = this.getNavigation(locale).getNavigationElementByDocumentId(documentId);
        if (navEl != null) {
            contentDocument.setPath(navEl.getPath());
        }

        return contentDocument;
    }

    private Navigation getNavigation(Locale locale) {
        return this.navigationDao.get(this.navigationDao.getNavDocId(), locale);
    }

    private static String createRelativizer(String path) {
        if (StringUtils.isBlank(path)) {
            return "";
        }

        String result = path;
        if (!result.startsWith("/")) {
            result = "/" + result;
        }

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < StringUtils.countMatches(path, "/"); i++) {
            sb.append("../");
        }

        return sb.toString();
    }
}

@@ -917,24 +917,471 @@
 cumentDao;%0A%0A
+    private static String createRelativizer(String path) %7B%0A        if (StringUtils.isBlank(path)) %7B%0A            return %22%22;%0A        %7D%0A%0A        String result = path;%0A        if (!result.startsWith(%22/%22)) %7B%0A            result = %22/%22 + result;%0A        %7D%0A%0A        StringBuilder sb = new StringBuilder();%0A        for (int i = 0; i %3C StringUtils.countMatches(path, %22/%22); i++) %7B%0A            sb.append(%22../%22);%0A        %7D%0A%0A        return sb.toString();%0A    %7D%0A%0A
     @Overrid
@@ -1374,32 +1374,32 @@
 %0A%0A    @Override%0A
-
     public List%3C
@@ -3400,24 +3400,118 @@
 ath(path);%0A%0A
+        if (currentElement == null) %7B%0A            return new NavigationElement%5B0%5D;%0A        %7D%0A%0A
         // n
@@ -4984,32 +4984,32 @@
 ocale locale) %7B%0A
+
         return t
@@ -5082,454 +5082,7 @@
    %7D
-%0A%0A    private static String createRelativizer(String path) %7B%0A        if (StringUtils.isBlank(path)) %7B%0A            return %22%22;%0A        %7D%0A%0A        String result = path;%0A        if (!result.startsWith(%22/%22)) %7B%0A            result = %22/%22 + result;%0A        %7D%0A%0A        StringBuilder sb = new StringBuilder();%0A        for (int i = 0; i %3C StringUtils.countMatches(path, %22/%22); i++) %7B%0A            sb.append(%22../%22);%0A        %7D%0A%0A        return sb.toString();%0A    %7D
 %0A%7D%0A

move the ContentDocumentModel to daisy-wicket; fix potential NPE in the content service