/*
* Copyright (C) 2007-2010 Geometer Plus <contact@geometerplus.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
package org.geometerplus.fbreader.formats.plucker;
//import java.io.IOException;
//import java.util.*;
//import java.util.zip.*;
//
//import org.geometerplus.zlibrary.core.constants.MimeTypes;
//import org.geometerplus.zlibrary.core.filesystem.ZLFile;
//import org.geometerplus.zlibrary.core.util.ZLInputStreamWithOffset;
//import org.geometerplus.zlibrary.core.image.*;
//import org.geometerplus.zlibrary.text.model.*;
//
//import org.geometerplus.fbreader.bookmodel.*;
//import org.geometerplus.fbreader.formats.pdb.*;
//
//public class PluckerBookReader extends BookReader {
// private final ZLFile myFile;
// private final int myFileSize;
// private ZLInputStreamWithOffset myStream;
// private int myFont;
// private char[] myCharBuffer;
// private String myConvertedTextBuffer;
// private boolean myParagraphStarted = false;
// private boolean myBufferIsEmpty;
// //private ZLTextForcedControlEntry myForcedEntry;
// private final ArrayList/*<std::pair<FBTextKind,bool> >*/ myDelayedControls = new ArrayList();
// private final ArrayList/*<std::string> */myDelayedHyperlinks = new ArrayList();
// private short myCompressionVersion;
// private char myBytesToSkip;
//
// private final ArrayList/*<std::pair<int, int> >*/ myReferencedParagraphs = new ArrayList();
// private final HashMap/*<int, std::vector<int> >*/ myParagraphMap = new HashMap(); /*<int, vector<pair<int, int>>>*/
// private ArrayList/*<Integer, Integer>*/ myParagraphVector = new ArrayList();
// private boolean myParagraphStored;
//
// public PluckerBookReader(ZLFile file, BookModel model, String encoding){
// super(model);
// //myConverter = new EncodedTextReader(encoding).getConverter();
// myFile = file;
// myFileSize = (int)file.size();
// //System.out.println(filePath + " " + encoding);
// myFont = FontType.FT_REGULAR;
// myCharBuffer = new char[65535];
// //myForcedEntry = null;
// }
//
// public boolean readDocument() {
// try {
// myStream = new ZLInputStreamWithOffset(myFile.getInputStream());
//
// PdbHeader header = new PdbHeader(myStream);
//
// setMainTextModel();
// myFont = FontType.FT_REGULAR;
//
// for (int index = 0; index < header.Offsets.length; ++index) {
// int currentOffset = myStream.offset();
// int pit = header.Offsets[index];
// if (currentOffset > pit) {
// break;
// }
// //myStream.seek(pit - currentOffset, false);
// myStream.skip(pit - currentOffset);
//
// if (myStream.offset() != pit) {
// break;
// }
// int recordSize = ((index != header.Offsets.length - 1) ? header.Offsets[index + 1] : myFileSize) - pit;
// readRecord(recordSize);
// }
// myStream.close();
// } catch (IOException e) {
// return false;
// }
//
// for (Iterator it = myReferencedParagraphs.iterator(); it.hasNext();) {
// Pair pair = (Pair)it.next();
// int first = (Integer)pair.myFirst;
// int second = (Integer)pair.mySecond;
// ArrayList/*<Integer>*/ list = (ArrayList)myParagraphMap.get(first);
// if (list != null) {
// for(int k = second; k < list.size(); ++k) {
// if (((Integer) ((Pair)list.get(k)).myFirst) != -1) {
// //addHyperlinkLabel(fromNumber(first) + '#' + fromNumber(second), (Integer)list.get(k));
// final Pair p = (Pair)list.get(k);
// //addHyperlinkLabel(fromNumber(first) + '#' + fromNumber(second), (Integer) p.mySecond, (Integer) p.myFirst);
// break;
// }
// }
// }
// }
// myReferencedParagraphs.clear();
// myParagraphMap.clear();
// return true;
// }
//
// private class FontType {
// public static final int FT_REGULAR = 0;
// public static final int FT_H1 = 1;
// public static final int FT_H2 = 2;
// public static final int FT_H3 = 3;
// public static final int FT_H4 = 4;
// public static final int FT_H5 = 5;
// public static final int FT_H6 = 6;
// public static final int FT_BOLD = 7;
// public static final int FT_TT = 8;
// public static final int FT_SMALL = 9;
// public static final int FT_SUB = 10;
// public static final int FT_SUP = 11;
// };
//
// private void readRecord(int recordSize) throws IOException {
// int uid = PdbUtil.readShort(myStream);
// if (uid == 1) {
// myCompressionVersion = (short) PdbUtil.readShort(myStream );
// } else {
// int paragraphs = PdbUtil.readShort(myStream);
//
// int size = PdbUtil.readShort(myStream);
// //TODO ??????
// int type = myStream.read();
//
// int flags = myStream.read();
//
// switch (type) {
// case 0: // text (TODO: found sample file and test this code)
// case 1: // compressed text
// {
// ArrayList/*<Integer>*/ pars = new ArrayList();
// for (int i = 0; i < paragraphs; ++i) {
// int pSize = PdbUtil.readShort(myStream);
// pars.add(pSize);
// myStream.skip(2);
// }
//
// boolean doProcess = false;
// if (type == 0) {//?
// byte[] buf = new byte[size];
// doProcess = myStream.read(buf, 0, (int)size) == size;
// if (doProcess) {
// // TODO: use encoding!!!!
// // TODO: don't create any new objects!!!!
// myCharBuffer = new String(buf).toCharArray();
// }
// } else if (myCompressionVersion == 1) {
// byte[] buf = new byte[size];
// doProcess =
// DocDecompressor.decompress(myStream, buf, recordSize - 8 - 4 * paragraphs) == size;
// if (doProcess) {
// myCharBuffer = new String(buf).toCharArray();
// }
// } else if (myCompressionVersion == 2) {
// byte input [] = new byte[(int) (recordSize - 10 - 4 * paragraphs)];
// final int inputSize = myStream.read(input);
// Inflater decompressor = new Inflater();
// decompressor.setInput(input, 0, inputSize);
// byte output [] = new byte[size];
// try {
// doProcess = decompressor.inflate(output) == size;
// decompressor.end();
// myCharBuffer = new String(output, 0, size).toCharArray();
// } catch (DataFormatException e) {
// // TODO Auto-generated catch block
// // e.printStackTrace();
// System.out.println(e.getMessage());
// }
// //doProcess =
// //ZLZDecompressor(recordSize - 10 - 4 * paragraphs).
// //decompress(myStream, myCharBuffer, size) == size;
// }
// if (doProcess) {
// addHyperlinkLabel(fromNumber(uid));
// myParagraphMap.put(uid, new ArrayList());
// myParagraphVector = (ArrayList)myParagraphMap.get(uid);
// processTextRecord(size, pars);
// if ((flags & 0x1) == 0) {
//// insertEndOfTextParagraph();
// //setNewTextModel();
// }
// }
// break;
// }
// case 2: // image
// case 3: // compressed image
// {
// ZLImage image = null;
// if (type == 2) {
// System.out.println("non-compressed image");
// image = new PluckerFileImage(MimeTypes.MIME_IMAGE_PALM, myFile, myStream.offset(), recordSize - 8);
// } else if (myCompressionVersion == 1) {
// System.out.println("DocCompressedImage");
// image = new DocCompressedFileImage(MimeTypes.MIME_IMAGE_PALM, myFile, myStream.offset(), recordSize - 8);
// } else if (myCompressionVersion == 2) {
// System.out.println("ZCompressedImage");
// image = new ZCompressedFileImage(MimeTypes.MIME_IMAGE_PALM, myFile, myStream.offset() + 2, recordSize - 10);
// }
// if (image != null) {
// addImage(fromNumber(uid), image);
// }
// break;
// }
// case 9: // category record is ignored
// break;
// case 10:
// short typeCode = (short) PdbUtil.readShort(myStream);
// break;
// case 11: // style sheet record is ignored
// break;
// case 12: // font page record is ignored
// break;
// case 13: // TODO: process tables
// case 14: // TODO: process tables
// break;
// case 15: // multiimage
// {
// short columns = (short) PdbUtil.readShort(myStream);
// short rows = (short) PdbUtil.readShort(myStream);
// System.out.println("multiimage");
// /*PluckerMultiImage image = new PluckerMultiImage(rows, columns, Model.getImageMap());
// for (int i = 0; i < size / 2 - 2; ++i) {
// short us = (short)myStream.read();
// PdbUtil.readShort(myStream, us);
// image.addId(fromNumber(us));
// }
// addImage(fromNumber(uid), image);
// */break;
// }
// default:
// //std::cerr << "type = " << (int)type << "\n";
// break;
// }
// }
// }
//
// private void processTextRecord(int size, ArrayList/*<Integer>*/ pars) {
// int start = 0;
// int end = 0;
//
// for (Iterator it = pars.iterator(); it.hasNext();) {
// start = end;
// end = start + (Integer)it.next();
// if (end > size) {
// return;
// }
// myParagraphStored = false;
// processTextParagraph(myCharBuffer, start, end);
// if (!myParagraphStored) {
// myParagraphVector.add(new Pair(-1, -1));
// }
// }
// }
//
// private void processTextParagraph(char[] data, int start, int end) {
// changeFont(FontType.FT_REGULAR);
// while (popKind()) {}
//
// myParagraphStarted = false;
// myBytesToSkip = 0;
//
// int textStart = start;
// boolean functionFlag = false;
// for (int ptr = start; ptr < end; ++ptr) {
// if (data[ptr] == 0) {
// functionFlag = true;
// if (ptr > textStart) {
// safeBeginParagraph();
// // myConvertedTextBuffer = "";//.erase();
// myConvertedTextBuffer = "";//myConverter.convert(data, textStart, ptr);
// addData(myConvertedTextBuffer.toCharArray());
// myBufferIsEmpty = false;
// }
// } else if (functionFlag) {
// int paramCounter = (data[ptr]) % 8;
// if (end - ptr > paramCounter) {
// processTextFunction(data, ptr);
// ptr += paramCounter;
// } else {
// ptr = end - 1;
// }
// functionFlag = false;
// if (myBytesToSkip > 0) {
// ptr += myBytesToSkip;
// myBytesToSkip = 0;
// }
// textStart = ptr + 1;
// } else {
// if (data[ptr] == 0xA0) {
// data[ptr] = 0x20;
// }
// if (!myParagraphStarted && (textStart == ptr) && (data[ptr] == ' ')) {
// ++textStart;
// }
// }
// }
// if (end > textStart) {
// safeBeginParagraph();
// // myConvertedTextBuffer = "";//erase();
// myConvertedTextBuffer = "";//myConverter.convert(data, textStart, end);
// addData(myConvertedTextBuffer.toCharArray());
// myBufferIsEmpty = false;
// }
// safeEndParagraph();
// //if (myForcedEntry != null) {
// // myForcedEntry = null;
// //}
// myDelayedControls.clear();
// }
//
// private void processTextFunction(char[] ptr, int cur) {
// switch (ptr[cur]) {
// case 0x08:
// safeAddControl(FBTextKind.INTERNAL_HYPERLINK, false);
// break;
// case 0x0A:
// safeAddHyperlinkControl(fromNumber(twoBytes(ptr, cur+ 1)));
// break;
// case 0x0C:
// {
// int sectionNum = twoBytes(ptr, cur + 1);
// int paragraphNum = twoBytes(ptr, cur + 3);
// safeAddHyperlinkControl(fromNumber(sectionNum) + '#' + fromNumber(paragraphNum));
// myReferencedParagraphs.add(new Pair(sectionNum, paragraphNum));
// break;
// }
// case 0x11:
// changeFont((ptr[cur + 1]));
// break;
// case 0x1A:
// safeBeginParagraph();
// // System.out.println("image ref");
// addImageReference(fromNumber(twoBytes(ptr, cur + 1)), (short) 0);
// break;
// case 0x22:
// if (!myParagraphStarted) {
// //if (myForcedEntry == null) {
// // myForcedEntry = new ZLTextForcedControlEntry();
// //}
// //myForcedEntry.setLeftIndent((short)ptr[cur + 1]);
// //myForcedEntry.setRightIndent((short)ptr[cur + 2]);
// }
// break;
// case 0x29:
// if (!myParagraphStarted) {
// //if (myForcedEntry == null) {
// // myForcedEntry = new ZLTextForcedControlEntry();
// //}
// //switch (ptr[cur + 1]) {
// // case 0: myForcedEntry.setAlignmentType(ZLTextAlignmentType.ALIGN_LEFT); break;
// // case 1: myForcedEntry.setAlignmentType(ZLTextAlignmentType.ALIGN_RIGHT); break;
// // case 2: myForcedEntry.setAlignmentType(ZLTextAlignmentType.ALIGN_CENTER); break;
// // case 3: myForcedEntry.setAlignmentType(ZLTextAlignmentType.ALIGN_JUSTIFY); break;
// //}
// }
// break;
// case 0x33: // just break line instead of horizontal rule (TODO: draw horizontal rule?)
// safeEndParagraph();
// break;
// case 0x38:
// safeEndParagraph();
// break;
// case 0x40:
// safeAddControl(FBTextKind.EMPHASIS, true);
// break;
// case 0x48:
// safeAddControl(FBTextKind.EMPHASIS, false);
// break;
// case 0x53: // color setting is ignored
// break;
// case 0x5C:
// // System.out.println("image ref");
// addImageReference(fromNumber(twoBytes(ptr, cur + 3)), (short) 0);
// break;
// case 0x60: // underlined text is ignored
// break;
// case 0x68: // underlined text is ignored
// break;
// case 0x70: // strike-through text is ignored
// break;
// case 0x78: // strike-through text is ignored
// break;
// case 0x83:
// {
// safeBeginParagraph();
// addData(new char[] { (char)twoBytes(ptr, cur + 2) });
// myBufferIsEmpty = false;
// myBytesToSkip = ptr[cur+1];
// break;
// }
// case 0x85: // TODO: process 4-byte unicode character
// break;
// case 0x8E: // custom font operations are ignored
// case 0x8C:
// case 0x8A:
// case 0x88:
// break;
// case 0x90: // TODO: add table processing
// case 0x92: // TODO: process table
// case 0x97: // TODO: process table
// break;
// default: // this should be impossible
// //std::cerr << "Oops... function #" << (int)(unsigned char)*ptr << "\n";
// break;
// }
// }
//
// private void setFont(int font, boolean start) {
// switch (font) {
// case FontType.FT_REGULAR:
// break;
// case FontType.FT_H1:
// case FontType.FT_H2:
// case FontType.FT_H3:
// case FontType.FT_H4:
// case FontType.FT_H5:
// case FontType.FT_H6:
// processHeader(font, start);
// break;
// case FontType.FT_BOLD:
// safeAddControl(FBTextKind.BOLD, start);
// break;
// case FontType.FT_TT:
// safeAddControl(FBTextKind.CODE, start);
// break;
// case FontType.FT_SMALL:
// break;
// case FontType.FT_SUB:
// safeAddControl(FBTextKind.SUB, start);
// break;
// case FontType.FT_SUP:
// safeAddControl(FBTextKind.SUP, start);
// break;
// }
// }
//
// private void changeFont(int font) {
// if (myFont == font) {
// return;
// }
// setFont(myFont, false);
// myFont = font;
// setFont(myFont, true);
// }
//
// private void safeAddControl(byte kind, boolean start) {
// if (myParagraphStarted) {
// addControl((Byte)kind, (Boolean)start);
// } else {
// myDelayedControls.add(new Pair(kind, start));
// }
// }
// private void safeAddHyperlinkControl(String id) {
// if (myParagraphStarted) {
// addHyperlinkControl(FBTextKind.INTERNAL_HYPERLINK, id);
// } else {
// myDelayedHyperlinks.add(id);
// }
// }
//
// private void safeBeginParagraph() {
// if (!myParagraphStarted) {
// myParagraphStarted = true;
// myBufferIsEmpty = true;
// beginParagraph(ZLTextParagraph.Kind.TEXT_PARAGRAPH);
// if (!myParagraphStored) {
// //final ArrayList models = Model.getBookTextModels();
// //myParagraphVector.add(new Pair(((ZLTextPlainModel) models.get(models.size()-1)/*BookTextModel*/).getParagraphsNumber() - 1, models.size() - 1));
// myParagraphStored = true;
// }
// for (Iterator it = myDelayedControls.iterator(); it.hasNext(); ) {
// Pair pit = (Pair)it.next();
// addControl((Byte)pit.myFirst, (Boolean)pit.mySecond);
// }
// //if (myForcedEntry != null) {
// // addControl(myForcedEntry);
// //} else {
// addControl(FBTextKind.REGULAR, true);
// //}
// for (Iterator it = myDelayedHyperlinks.iterator(); it.hasNext(); ) {
// addHyperlinkControl(FBTextKind.INTERNAL_HYPERLINK, (String)it.next());
// }
// myDelayedHyperlinks.clear();
// }
// }
//
// private void safeEndParagraph() {
// if (myParagraphStarted) {
// if (myBufferIsEmpty) {
// final String SPACE = " ";
// addData(SPACE.toCharArray());
// }
// endParagraph();
// myParagraphStarted = false;
// }
// }
//
// private void processHeader(int font, boolean start) {
// if (start) {
// enterTitle();
// int kind;
// switch (font) {
// case FontType.FT_H1:
// kind = FBTextKind.H1;
// break;
// case FontType.FT_H2:
// kind = FBTextKind.H2;
// break;
// case FontType.FT_H3:
// kind = FBTextKind.H3;
// break;
// case FontType.FT_H4:
// kind = FBTextKind.H4;
// break;
// case FontType.FT_H5:
// kind = FBTextKind.H5;
// break;
// case FontType.FT_H6:
// default:
// kind = FBTextKind.H6;
// break;
// }
// pushKind((byte)kind);
// } else {
// popKind();
// exitTitle();
// }
// }
//
// static private class Pair {
// public Object myFirst;
// public Object mySecond;
// Pair(Object first, Object second) {
// this.myFirst = first;
// this.mySecond = second;
// }
// }
//
// static private int twoBytes(char[] ptr, int offset) {
// return 256 * ptr[offset] + ptr[offset+1];
// }
//
// static String fromNumber(int num) {
// String str = "";
// str += num;
// //ZLStringUtil.appendNumber(str, num);
// return str;
// }
//}