/* ====================================================================
   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.apache.poi.hslf.usermodel;

import java.io.Closeable;
import java.io.IOException;
import java.io.OutputStream;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;

import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.hslf.exceptions.CorruptPowerPointFileException;
import org.apache.poi.hslf.exceptions.EncryptedPowerPointFileException;
import org.apache.poi.hslf.record.DocumentEncryptionAtom;
import org.apache.poi.hslf.record.PersistPtrHolder;
import org.apache.poi.hslf.record.PositionDependentRecord;
import org.apache.poi.hslf.record.Record;
import org.apache.poi.hslf.record.UserEditAtom;
import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey;
import org.apache.poi.poifs.crypt.ChunkedCipherInputStream;
import org.apache.poi.poifs.crypt.ChunkedCipherOutputStream;
import org.apache.poi.poifs.crypt.Decryptor;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIDecryptor;
import org.apache.poi.poifs.crypt.cryptoapi.CryptoAPIEncryptor;
import org.apache.poi.util.BitField;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianByteArrayOutputStream;

/**
 * This class provides helper functions for encrypted PowerPoint documents.
 */
@Internal
public class HSLFSlideShowEncrypted implements Closeable {
    DocumentEncryptionAtom dea;
    CryptoAPIEncryptor enc = null;
    CryptoAPIDecryptor dec = null;
//    Cipher cipher = null;
    ChunkedCipherOutputStream cyos = null;

    private static final BitField fieldRecInst = new BitField(0xFFF0);

    private static final int BLIB_STORE_ENTRY_PARTS[] = {
        1,     // btWin32
        1,     // btMacOS
        16,    // rgbUid
        2,     // tag
        4,     // size
        4,     // cRef
        4,     // foDelay
        1,     // unused1
        1,     // cbName (@ index 33)
        1,     // unused2
        1,     // unused3
    };
    
    protected HSLFSlideShowEncrypted(DocumentEncryptionAtom dea) {
        this.dea = dea;
    }

    protected HSLFSlideShowEncrypted(byte[] docstream, NavigableMap<Integer,Record> recordMap) {
        // check for DocumentEncryptionAtom, which would be at the last offset
        // need to ignore already set UserEdit and PersistAtoms
        UserEditAtom userEditAtomWithEncryption = null;
        for (Map.Entry<Integer, Record> me : recordMap.descendingMap().entrySet()) {
            Record r = me.getValue();
            if (!(r instanceof UserEditAtom)) {
                continue;
            }
            UserEditAtom uea = (UserEditAtom)r;
            if (uea.getEncryptSessionPersistIdRef() != -1) {
                userEditAtomWithEncryption = uea;
                break;
            }
        }

        if (userEditAtomWithEncryption == null) {
            dea = null;
            return;
        }

        Record r = recordMap.get(userEditAtomWithEncryption.getPersistPointersOffset());
        assert(r instanceof PersistPtrHolder);
        PersistPtrHolder ptr = (PersistPtrHolder)r;

        Integer encOffset = ptr.getSlideLocationsLookup().get(userEditAtomWithEncryption.getEncryptSessionPersistIdRef());
        if (encOffset == null) {
            // encryption info doesn't exist anymore
        	// SoftMaker Freeoffice produces such invalid files - check for "SMNativeObjData" ole stream
            dea = null;
            return;
        }

        r = recordMap.get(encOffset);
        if (r == null) {
            r = Record.buildRecordAtOffset(docstream, encOffset);
            recordMap.put(encOffset, r);
        }
        assert(r instanceof DocumentEncryptionAtom);
        this.dea = (DocumentEncryptionAtom)r;
        decryptInit();

        String pass = Biff8EncryptionKey.getCurrentUserPassword();
        if(!dec.verifyPassword(pass != null ? pass : Decryptor.DEFAULT_PASSWORD)) {
            throw new EncryptedPowerPointFileException("PowerPoint file is encrypted. The correct password needs to be set via Biff8EncryptionKey.setCurrentUserPassword()");
        }
     }

    public DocumentEncryptionAtom getDocumentEncryptionAtom() {
        return dea;
    }

    protected void decryptInit() {
        if (dec != null) {
            return;
        }
        EncryptionInfo ei = dea.getEncryptionInfo();
        dec = (CryptoAPIDecryptor)ei.getDecryptor();
    }

    protected void encryptInit() {
        if (enc != null) {
            return;
        }
        EncryptionInfo ei = dea.getEncryptionInfo();
        enc = (CryptoAPIEncryptor)ei.getEncryptor();
    }



    protected OutputStream encryptRecord(OutputStream plainStream, int persistId, Record record) {
        boolean isPlain = (dea == null
            || record instanceof UserEditAtom
            || record instanceof PersistPtrHolder
            || record instanceof DocumentEncryptionAtom
        );

        try {
            if (isPlain) {
                if (cyos != null) {
                    // write cached data to stream
                    cyos.flush();
                }
                return plainStream;
            }

            encryptInit();

            if (cyos == null) {
                enc.setChunkSize(-1);
                cyos = enc.getDataStream(plainStream, 0);
            }
            cyos.initCipherForBlock(persistId, false);
        } catch (Exception e) {
            throw new EncryptedPowerPointFileException(e);
        }
        return cyos;
    }

    private static void readFully(ChunkedCipherInputStream ccis, byte[] docstream, int offset, int len) throws IOException {
        if (IOUtils.readFully(ccis, docstream, offset, len) == -1) {
            throw new EncryptedPowerPointFileException("unexpected EOF");
        }
    }

    protected void decryptRecord(byte[] docstream, int persistId, int offset) {
        if (dea == null) {
            return;
        }

        decryptInit();
        dec.setChunkSize(-1);
        LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(docstream, offset); // NOSONAR
        ChunkedCipherInputStream ccis = null;
        try {
            ccis = dec.getDataStream(lei, docstream.length-offset, 0);
            ccis.initCipherForBlock(persistId);

            // decrypt header and read length to be decrypted
            readFully(ccis, docstream, offset, 8);
            // decrypt the rest of the record
            int rlen = (int)LittleEndian.getUInt(docstream, offset+4);
            readFully(ccis, docstream, offset+8, rlen);

        } catch (Exception e) {
            throw new EncryptedPowerPointFileException(e);
        } finally {
            IOUtils.closeQuietly(ccis);
            IOUtils.closeQuietly(lei);
        }
    }

    private void decryptPicBytes(byte[] pictstream, int offset, int len)
    throws IOException, GeneralSecurityException {
        // when reading the picture elements, each time a segment is read, the cipher needs
        // to be reset (usually done when calling Cipher.doFinal)
        LittleEndianByteArrayInputStream lei = new LittleEndianByteArrayInputStream(pictstream, offset);
        ChunkedCipherInputStream ccis = dec.getDataStream(lei, len, 0);
        readFully(ccis, pictstream, offset, len);
        ccis.close();
        lei.close();
    }
    
    protected void decryptPicture(byte[] pictstream, int offset) {
        if (dea == null) {
            return;
        }

        decryptInit();

        try {
            // decrypt header and read length to be decrypted
            decryptPicBytes(pictstream, offset, 8);
            int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
            int recType = LittleEndian.getUShort(pictstream, offset+2);
            int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
            offset += 8;
            int endOffset = offset + rlen;

            if (recType == 0xF007) {
                // TOOD: get a real example file ... to actual test the FBSE entry
                // not sure where the foDelay block is

                // File BLIP Store Entry (FBSE)
                for (int part : BLIB_STORE_ENTRY_PARTS) {
                    decryptPicBytes(pictstream, offset, part);
                }
                offset += 36;
                
                int cbName = LittleEndian.getUShort(pictstream, offset-3);
                if (cbName > 0) {
                    // read nameData
                    decryptPicBytes(pictstream, offset, cbName);
                    offset += cbName;
                }
                
                if (offset == endOffset) {
                    return; // no embedded blip
                }
                // fall through, read embedded blip now

                // update header data
                decryptPicBytes(pictstream, offset, 8);
                recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
                recType = LittleEndian.getUShort(pictstream, offset+2);
                // rlen = (int)LittleEndian.getUInt(pictstream, offset+4);
                offset += 8;
            }

            int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 ||
                recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1;

            // rgbUid 1/2
            for (int i=0; i<rgbUidCnt; i++) {
                decryptPicBytes(pictstream, offset, 16);
                offset += 16;
            }

            int nextBytes;
            if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
                // metafileHeader
                nextBytes = 34;
            } else {
                // tag
                nextBytes = 1;
            }
            
            decryptPicBytes(pictstream, offset, nextBytes);
            offset += nextBytes;

            int blipLen = endOffset - offset;
            decryptPicBytes(pictstream, offset, blipLen);
        } catch (Exception e) {
            throw new CorruptPowerPointFileException(e);
        }
    }

    protected void encryptPicture(byte[] pictstream, int offset) {
        if (dea == null) {
            return;
        }

        encryptInit();

        LittleEndianByteArrayOutputStream los = new LittleEndianByteArrayOutputStream(pictstream, offset); // NOSONAR
        ChunkedCipherOutputStream ccos = null;

        try {
            enc.setChunkSize(-1);
            ccos = enc.getDataStream(los, 0);
            int recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
            int recType = LittleEndian.getUShort(pictstream, offset+2);
            final int rlen = (int)LittleEndian.getUInt(pictstream, offset+4);

            ccos.write(pictstream, offset, 8);
            ccos.flush();
            offset += 8;
            int endOffset = offset + rlen;

            if (recType == 0xF007) {
                // TOOD: get a real example file ... to actual test the FBSE entry
                // not sure where the foDelay block is

                // File BLIP Store Entry (FBSE)
                int cbName = LittleEndian.getUShort(pictstream, offset+33);
                
                for (int part : BLIB_STORE_ENTRY_PARTS) {
                    ccos.write(pictstream, offset, part);
                    ccos.flush();
                    offset += part;
                }
                
                if (cbName > 0) {
                    ccos.write(pictstream, offset, cbName);
                    ccos.flush();
                    offset += cbName;
                }
                
                if (offset == endOffset) {
                    return; // no embedded blip
                }
                // fall through, read embedded blip now

                // update header data
                recInst = fieldRecInst.getValue(LittleEndian.getUShort(pictstream, offset));
                recType = LittleEndian.getUShort(pictstream, offset+2);
                ccos.write(pictstream, offset, 8);
                ccos.flush();
                offset += 8;
            }

            int rgbUidCnt = (recInst == 0x217 || recInst == 0x3D5 || recInst == 0x46B || recInst == 0x543 ||
                recInst == 0x6E1 || recInst == 0x6E3 || recInst == 0x6E5 || recInst == 0x7A9) ? 2 : 1;

            for (int i=0; i<rgbUidCnt; i++) {
                ccos.write(pictstream, offset, 16); // rgbUid 1/2
                ccos.flush();
                offset += 16;
            }

            if (recType == 0xF01A || recType == 0XF01B || recType == 0XF01C) {
                ccos.write(pictstream, offset, 34); // metafileHeader
                offset += 34;
                ccos.flush();
            } else {
                ccos.write(pictstream, offset, 1); // tag
                offset += 1;
                ccos.flush();
            }

            int blipLen = endOffset - offset;
            ccos.write(pictstream, offset, blipLen);
            ccos.flush();
        } catch (Exception e) {
            throw new EncryptedPowerPointFileException(e);
        } finally {
            IOUtils.closeQuietly(ccos);
            IOUtils.closeQuietly(los);
        }
    }

    protected Record[] updateEncryptionRecord(Record records[]) {
        String password = Biff8EncryptionKey.getCurrentUserPassword();
        if (password == null) {
            if (dea == null) {
                // no password given, no encryption record exits -> done
                return records;
            } else {
                // need to remove password data
                dea = null;
                return removeEncryptionRecord(records);
            }
        } else {
            // create password record
            if (dea == null) {
                dea = new DocumentEncryptionAtom();
                enc = null;
            }
            encryptInit();
            EncryptionInfo ei = dea.getEncryptionInfo();
            byte salt[] = ei.getVerifier().getSalt();
            if (salt == null) {
                enc.confirmPassword(password);
            } else {
                byte verifier[] = ei.getDecryptor().getVerifier();
                enc.confirmPassword(password, null, null, verifier, salt, null);
            }

            // move EncryptionRecord to last slide position
            records = normalizeRecords(records);
            return addEncryptionRecord(records, dea);
        }
    }

    /**
     * remove duplicated UserEditAtoms and merge PersistPtrHolder.
     * Before this method is called, make sure that the offsets are correct,
     * i.e. call {@link HSLFSlideShowImpl#updateAndWriteDependantRecords(OutputStream, Map)}
     */
    protected static Record[] normalizeRecords(Record records[]) {
        // http://msdn.microsoft.com/en-us/library/office/gg615594(v=office.14).aspx
        // repeated slideIds can be overwritten, i.e. ignored

        UserEditAtom uea = null;
        PersistPtrHolder pph = null;
        TreeMap<Integer,Integer> slideLocations = new TreeMap<Integer,Integer>();
        TreeMap<Integer,Record> recordMap = new TreeMap<Integer,Record>();
        List<Integer> obsoleteOffsets = new ArrayList<Integer>();
        int duplicatedCount = 0;
        for (Record r : records) {
            assert(r instanceof PositionDependentRecord);
            PositionDependentRecord pdr = (PositionDependentRecord)r;
            if (pdr instanceof UserEditAtom) {
                uea = (UserEditAtom)pdr;
                continue;
            }

            if (pdr instanceof PersistPtrHolder) {
                if (pph != null) {
                    duplicatedCount++;
                }
                pph = (PersistPtrHolder)pdr;
                for (Map.Entry<Integer,Integer> me : pph.getSlideLocationsLookup().entrySet()) {
                    Integer oldOffset = slideLocations.put(me.getKey(), me.getValue());
                    if (oldOffset != null) {
                        obsoleteOffsets.add(oldOffset);
                    }
                }
                continue;
            }

            recordMap.put(pdr.getLastOnDiskOffset(), r);
        }

        if (uea == null || pph == null || uea.getPersistPointersOffset() != pph.getLastOnDiskOffset()) {
            throw new EncryptedDocumentException("UserEditAtom and PersistPtrHolder must exist and their offset need to match.");
        }

        recordMap.put(pph.getLastOnDiskOffset(), pph);
        recordMap.put(uea.getLastOnDiskOffset(), uea);

        if (duplicatedCount == 0 && obsoleteOffsets.isEmpty()) {
            return records;
        }

        uea.setLastUserEditAtomOffset(0);
        pph.clear();
        for (Map.Entry<Integer,Integer> me : slideLocations.entrySet()) {
            pph.addSlideLookup(me.getKey(), me.getValue());
        }

        for (Integer oldOffset : obsoleteOffsets) {
            recordMap.remove(oldOffset);
        }

        return recordMap.values().toArray(new Record[recordMap.size()]);
    }


    protected static Record[] removeEncryptionRecord(Record records[]) {
        int deaSlideId = -1;
        int deaOffset = -1;
        PersistPtrHolder ptr = null;
        UserEditAtom uea = null;
        List<Record> recordList = new ArrayList<Record>();
        for (Record r : records) {
            if (r instanceof DocumentEncryptionAtom) {
                deaOffset = ((DocumentEncryptionAtom)r).getLastOnDiskOffset();
                continue;
            } else if (r instanceof UserEditAtom) {
                uea = (UserEditAtom)r;
                deaSlideId = uea.getEncryptSessionPersistIdRef();
                uea.setEncryptSessionPersistIdRef(-1);
            } else if (r instanceof PersistPtrHolder) {
                ptr = (PersistPtrHolder)r;
            }
            recordList.add(r);
        }

        if (ptr == null || uea == null) {
            throw new EncryptedDocumentException("UserEditAtom or PersistPtrholder not found.");
        }
        if (deaSlideId == -1 && deaOffset == -1) {
            return records;
        }

        TreeMap<Integer,Integer> tm = new TreeMap<Integer,Integer>(ptr.getSlideLocationsLookup());
        ptr.clear();
        int maxSlideId = -1;
        for (Map.Entry<Integer,Integer> me : tm.entrySet()) {
            if (me.getKey() == deaSlideId || me.getValue() == deaOffset) {
                continue;
            }
            ptr.addSlideLookup(me.getKey(), me.getValue());
            maxSlideId = Math.max(me.getKey(), maxSlideId);
        }

        uea.setMaxPersistWritten(maxSlideId);

        records = recordList.toArray(new Record[recordList.size()]);

        return records;
    }


    protected static Record[] addEncryptionRecord(Record records[], DocumentEncryptionAtom dea) {
        assert(dea != null);
        int ueaIdx = -1, ptrIdx = -1, deaIdx = -1, idx = -1;
        for (Record r : records) {
            idx++;
            if (r instanceof UserEditAtom) {
                ueaIdx = idx;
            } else if (r instanceof PersistPtrHolder) {
                ptrIdx = idx;
            } else if (r instanceof DocumentEncryptionAtom) {
                deaIdx = idx;
            }
        }
        assert(ueaIdx != -1 && ptrIdx != -1 && ptrIdx < ueaIdx);
        if (deaIdx != -1) {
            DocumentEncryptionAtom deaOld = (DocumentEncryptionAtom)records[deaIdx];
            dea.setLastOnDiskOffset(deaOld.getLastOnDiskOffset());
            records[deaIdx] = dea;
            return records;
        } else {
            PersistPtrHolder ptr = (PersistPtrHolder)records[ptrIdx];
            UserEditAtom uea = ((UserEditAtom)records[ueaIdx]);
            dea.setLastOnDiskOffset(ptr.getLastOnDiskOffset()-1);
            int nextSlideId = uea.getMaxPersistWritten()+1;
            ptr.addSlideLookup(nextSlideId, ptr.getLastOnDiskOffset()-1);
            uea.setEncryptSessionPersistIdRef(nextSlideId);
            uea.setMaxPersistWritten(nextSlideId);

            Record newRecords[] = new Record[records.length+1];
            if (ptrIdx > 0) {
                System.arraycopy(records, 0, newRecords, 0, ptrIdx);
            }
            if (ptrIdx < records.length-1) {
                System.arraycopy(records, ptrIdx, newRecords, ptrIdx+1, records.length-ptrIdx);
            }
            newRecords[ptrIdx] = dea;
            return newRecords;
        }
    }

    @Override
    public void close() throws IOException {
        if (cyos != null) {
            cyos.close();
        }
    }
}
