/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.netbeans.modules.properties;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.openide.filesystems.FileObject;
import org.openide.loaders.DataObject;
import org.openide.loaders.DataObjectNotFoundException;
import org.openide.util.Exceptions;

/**
 *
 * @author alexeybutenko
 */
class MultiBundleStructure extends BundleStructure implements Serializable {

    private transient FileObject[] files;
    private transient FileObject parent;
    private transient PropertiesFileEntry primaryEntry;
    private String baseName;
    private String extension;

    /** Generated Serialized Version UID. */
    static final long serialVersionUID = 7501232754255253334L;

    private transient PropertiesOpen openSupport;
    /** Lock used for synchronization of <code>openSupport</code> instance creation */
    private final transient Object OPEN_SUPPORT_LOCK = new Object();


    protected MultiBundleStructure() {
//        super();
//        files = null;
//        primaryEntry = null;
//        baseName = null;
    }

    public MultiBundleStructure(PropertiesDataObject obj) {
//        super(obj);
        this.obj = obj;
        baseName = Util.getBaseName(obj.getName());
        extension = PropertiesDataLoader.PROPERTIES_EXTENSION;
    }

    /**
     * Find entries according to PropertiesDataObject
     *
     */
    private synchronized void findEntries() {
//        try {
            if (obj != null) {
                if (!obj.isValid()) {
                    primaryEntry = null;
                    if (files!=null && files.length == 1) {
                        obj = null;
                        files = null;
                        return;
                    }
                } else {
//                    obj = Util.findPrimaryDataObject(obj);
                    primaryEntry = (PropertiesFileEntry) obj.getPrimaryEntry();
                }
            } else {
                return;
            }
            if (primaryEntry != null) {
                FileObject primary = primaryEntry.getFile();
                if(!primary.hasExt(extension)) {
                    if (primary.getMIMEType().equalsIgnoreCase(PropertiesDataLoader.PROPERTIES_MIME_TYPE))
                        extension = primary.getExt();
                }
                parent = primary.getParent();
            } else {
                if (parent == null) {
                    return;
                }
            }
            List<FileObject> listFileObjects = new ArrayList<FileObject>();
            String fName;
            FileObject oldCandidate;
            for (FileObject file : parent.getChildren()) {
                if (!file.hasExt(extension) || !file.getMIMEType().equalsIgnoreCase(PropertiesDataLoader.PROPERTIES_MIME_TYPE)) {
                    continue;
                }
                fName = file.getName();
                if (fName.equals(baseName) && file.isValid()) {
                    listFileObjects.add(0,file);
                }
                if (fName.indexOf(baseName) != -1) {
                    int index = fName.indexOf(PropertiesDataLoader.PRB_SEPARATOR_CHAR, baseName.length() - 1);
                    if (index == baseName.length()) {
                         if (file != null && isValidLocaleSuffix(fName.substring(index)) && file.isValid()) {
                            listFileObjects.add(file);
                        }
                    }
                }
            }
            if (listFileObjects.isEmpty()) {
                // a fallback if no other entries found
                files = new FileObject[] {obj.getPrimaryFile()};
                return;
            }
            files = listFileObjects.toArray(new FileObject[listFileObjects.size()]);
            if (primaryEntry != getNthEntry(0)) {
                //TODO XXX This means that primaryEntry has changed, so need to notify openSupport
                primaryEntry = getNthEntry(0);
                if (primaryEntry != null) {
                    notifyOneFileChanged(primaryEntry.getFile());
                    if(!primaryEntry.getFile().hasExt(extension)) {
                        if (primaryEntry.getFile().getMIMEType().equalsIgnoreCase(PropertiesDataLoader.PROPERTIES_MIME_TYPE))
                            extension = primaryEntry.getFile().getExt();
                    }
                    parent = primaryEntry.getFile().getParent();
                    obj = (PropertiesDataObject) primaryEntry.getDataObject();
                    baseName = Util.getBaseName(obj.getName());
                }
            }
//        } catch (DataObjectNotFoundException ex) {
//            Exceptions.printStackTrace(ex);
//        }
    }

    @Override
    void updateEntries() {
        findEntries();
        if (files != null) {
            buildKeySet();
        }
    }

    /**
     * Moves entry from fromIndex to toIndex shifting the rest elements
     * This method used in @see BundleEditPanel when switching columns order
     * @param fromIndex
     * @param toIndex
     */
    void moveEntry(int fromIndex, int toIndex) {
        if (fromIndex >= 0 && fromIndex < getEntryCount() && toIndex>=0 && toIndex < getEntryCount()) {
            int sortIndex = getSortIndex();
            if ((fromIndex+1) == sortIndex)
                sortIndex = toIndex+1;
            FileObject tmpFO = null;
            if (fromIndex < toIndex) {
                tmpFO = files[fromIndex];
                for (int i=fromIndex; i<toIndex;i++) {
                    files[i] = files[i+1];
                    if (i == sortIndex-1) sortIndex--;
                }
                files[toIndex] = tmpFO;
            } else if (fromIndex > toIndex) {
                tmpFO = files[fromIndex];
                for (int i=fromIndex;i>toIndex;i--) {
                    files[i] = files[i-1];
                    if(i == sortIndex-1) sortIndex++;
                }
                files[toIndex]=tmpFO;
            }
            if (getSortIndex()==toIndex+1) {
                sortIndex = fromIndex+1;
            }
            if (sortIndex != getSortIndex()) {
                boolean ascending = getSortOrder();
                sort(sortIndex);
                //preserving the sort order
                if (!ascending) 
                    sort(sortIndex);
            }
        }
    }

    @Override
    public PropertiesFileEntry getNthEntry(int index) {
        if (files == null) {
            return null;//super.getNthEntry(index);
//            notifyEntriesNotInitialized();
        }
        if (index >= 0 && index < files.length) {
            try {
                DataObject dataObject = DataObject.find(files[index]);
                if (dataObject instanceof PropertiesDataObject) {
                    return (PropertiesFileEntry) ((PropertiesDataObject)dataObject).getPrimaryEntry();
                }
            } catch (DataObjectNotFoundException ex) {
//                ex.printStackTrace();
            }
        } 
        return null;
    }

    /**
     * Retrieves an index of a file entry representing the given file.
     *
     * @param  fileName  simple name (without path and extension) of the
     *                   primary or secondary file
     * @return  index of the entry representing a file with the given filename;
     *          or <code>-1</code> if no such entry is found
     * @exception  java.lang.IllegalStateException
     *             if the list of entries has not been initialized yet
     * @see  #getEntryByFileName
     */
    @Override
    public int getEntryIndexByFileName(String fileName) {
        if (files == null) {
//            notifyEntriesNotInitialized();
            return -1;
        }
        for (int i = 0; i < getEntryCount(); i++) {
            if (files[i].getName().equals(fileName)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Retrieves a file entry representing the given file
     *
     * @param  fileName  simple name (excl. path, incl. extension) of the
     *                   primary or secondary file
     * @return  entry representing the given file;
     *          or <code>null</code> if not such entry is found
     * @exception  java.lang.IllegalStateException
     *             if the list of entries has not been initialized yet
     * @see  #getEntryIndexByFileName
     */
    @Override
    public PropertiesFileEntry getEntryByFileName(String fileName) {
        int index = getEntryIndexByFileName(fileName);
        try {
            return (index == -1) ? null : (PropertiesFileEntry) ((PropertiesDataObject) DataObject.find(files[index])).getPrimaryEntry();
        } catch (DataObjectNotFoundException ex) {
            Exceptions.printStackTrace(ex);
            return null;
        }
    }

    /**
     * Retrieves number of file entries.
     *
     * @return  number of file entries
     * @exception  java.lang.IllegalStateException
     *             if the list of entries has not been initialized yet
     */
    @Override
    public int getEntryCount() {
        if (files == null) {
            return 0;//super.getEntryCount();
//            notifyEntriesNotInitialized();
        }
        return files.length;
    }

    /**
     * Throws a runtime exception with a message that the entries
     * have not been initialized yet.
     *
     * @exception  java.lang.IllegalStateException  thrown always
     * @see  #updateEntries
     */
    private void notifyEntriesNotInitialized() {
        throw new IllegalStateException(
                "Resource Bundles: Entries not initialized");           //NOI18N
    }

    private static boolean isValidLocaleSuffix(String s) {
        // first char is _
        int n = s.length();
        String s1;
        // check first suffix - language (two chars)
        if (n == 3 || (n > 3 && s.charAt(3) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
            s1 = s.substring(1, 3).toLowerCase();
        // language must be followed by a valid country suffix or no suffix
        } else {
            return false;
        }
        // check second suffix - country (two chars)
        String s2;
        if (n == 3) {
            s2 = null;
        } else if (n == 6 || (n > 6 && s.charAt(6) == PropertiesDataLoader.PRB_SEPARATOR_CHAR)) {
            s2 = s.substring(4, 6).toUpperCase();
        // country may be followed by whatever additional suffix
        } else {
            return false;
        }

        Set<String> knownLanguages = new HashSet<String>(Arrays.asList(Locale.getISOLanguages()));
        if (!knownLanguages.contains(s1)) {
            return false;
        }

        if (s2 != null) {
            Set<String> knownCountries = new HashSet<String>(Arrays.asList(Locale.getISOCountries()));
            if (!knownCountries.contains(s2)) {
                return false;
            }
        }
        return true;
    }

    @Override
    public PropertiesOpen getOpenSupport() {
        synchronized (OPEN_SUPPORT_LOCK) {
            if (openSupport == null) {
                openSupport = new PropertiesOpen(this);
            }
            return openSupport;
        }
    }

    @Override
    public int getKeyCount() {
        try {
            return super.getKeyCount();
        } catch (IllegalStateException ie) {
            return 0;
        }
    }

    @Override
    PropertiesFileEntry[] getEntries() {
       
        synchronized (this) {
            if (files == null) {
                return new PropertiesFileEntry[0];
            } else {
                ArrayList<PropertiesFileEntry> entries = new ArrayList<PropertiesFileEntry>(files.length);
                try {
                    for (FileObject fileObject : files) {

                        DataObject dataObject = DataObject.find(fileObject);
                        if (dataObject instanceof PropertiesDataObject) {
                           entries.add((PropertiesFileEntry) ((PropertiesDataObject) dataObject).getPrimaryEntry());
                        }
                    }
                } catch (DataObjectNotFoundException ex) {
//                ex.printStackTrace();
                }
                if(entries.isEmpty()){
                    return new PropertiesFileEntry[0];
                } else {
                    return entries.toArray(new PropertiesFileEntry[entries.size()]);
                }
            }
        }
    }
    
    
}
