<commit_before>/*
 * Copyright 2014-2016 <NAME>
 * 
 * Licensed 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 com.mishiranu.dashchan.async;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;

import android.graphics.Typeface;
import android.net.Uri;
import android.text.SpannableStringBuilder;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;

import chan.content.ChanConfiguration;
import chan.content.ChanLocator;
import chan.content.ChanMarkup;
import chan.content.model.Attachment;
import chan.content.model.FileAttachment;
import chan.content.model.Icon;
import chan.content.model.Post;
import chan.content.model.Posts;
import chan.util.StringUtils;

import com.mishiranu.dashchan.app.MainApplication;
import com.mishiranu.dashchan.app.service.DownloadService;
import com.mishiranu.dashchan.preference.Preferences;
import com.mishiranu.dashchan.text.HtmlParser;
import com.mishiranu.dashchan.text.WakabaLikeHtmlBuilder;
import com.mishiranu.dashchan.text.style.GainedColorSpan;
import com.mishiranu.dashchan.text.style.HeadingSpan;
import com.mishiranu.dashchan.text.style.LinkSpan;
import com.mishiranu.dashchan.text.style.MonospaceSpan;
import com.mishiranu.dashchan.text.style.OverlineSpan;
import com.mishiranu.dashchan.text.style.QuoteSpan;
import com.mishiranu.dashchan.text.style.ScriptSpan;
import com.mishiranu.dashchan.text.style.SpoilerSpan;
import com.mishiranu.dashchan.util.IOUtils;

public class SendLocalArchiveTask extends CancellableTask<Void, Integer, Object> implements ChanMarkup.MarkupExtra
{
	private final String mChanName;
	private final String mBoardName;
	private final String mThreadNumber;
	private final Posts mPosts;
	private final boolean mSaveThumbnails;
	private final boolean mSaveFiles;
	private final Callback mCallback;
	
	public static interface Callback
	{
		public void onLocalArchivationProgressUpdate(int handledPostsCount);
		public void onLocalArchivationComplete(boolean success, boolean showSuccess);
	}
	
	public SendLocalArchiveTask(String chanName, String boardName, String threadNumber,
			Posts posts, boolean saveThumbnails, boolean saveFiles, Callback callback)
	{
		mChanName = chanName;
		mBoardName = boardName;
		mThreadNumber = threadNumber;
		mPosts = posts;
		mSaveThumbnails = saveThumbnails;
		mSaveFiles = saveFiles;
		mCallback = callback;
	}
	
	@Override
	public String getBoardName()
	{
		return mBoardName;
	}
	
	@Override
	public String getThreadNumber()
	{
		return mThreadNumber;
	}
	
	private static class SpanItem
	{
		public int start;
		public int end;
		
		public final String openTag;
		public final String closeTag;
		
		public SpanItem(String openTag, String closeTag)
		{
			this.openTag = openTag;
			this.closeTag = closeTag;
		}
	}
	
	@Override
	protected Result doInBackground(Void... params)
	{
		String chanName = mChanName;
		String boardName = mBoardName;
		String threadNumber = mThreadNumber;
		Post[] posts = mPosts.getPosts();
		Object[] decodeTo = new Object[2];
		ArrayList<SpanItem> spanItems = new ArrayList<>();
		ChanConfiguration configuration = ChanConfiguration.get(mChanName);
		ChanLocator locator = ChanLocator.get(configuration);
		ChanMarkup markup = ChanMarkup.get(configuration);
		File directory = getLocalDownloadDirectory(true);
		String archiveDirectoryName = chanName + '-' + boardName + '-' + threadNumber;
		File filesDirectory = mSaveFiles ? new File(directory, archiveDirectoryName + "/src") : null;
		File thumbnailsDirectory = mSaveThumbnails ? new File(directory, archiveDirectoryName + "/thumb") : null;
		if (filesDirectory != null) filesDirectory.mkdirs();
		if (thumbnailsDirectory != null) thumbnailsDirectory.mkdirs();
		int totalFilesCount = 0;
		ArrayList<String> existFilesLc = new ArrayList<>();
		ArrayList<String> existThumbnailsLc = new ArrayList<>();
		for (Post post : posts) totalFilesCount += post.getAttachmentsCount();
		String defaultName = configuration.getDefaultName(boardName);
		WakabaLikeHtmlBuilder htmlBuilder = new WakabaLikeHtmlBuilder(posts[0].getSubject(), chanName, boardName,
				configuration .getBoardTitle(boardName), configuration.getTitle(),
				locator.safe(false).createThreadUri(boardName, threadNumber), posts.length, totalFilesCount);
		Result result = new Result(thumbnailsDirectory, filesDirectory);
		for (Post post : posts)
		{
			String number = post.getPostNumber();
			String name = StringUtils.emptyIfNull(post.getName()).trim();
			String identifier = post.getIdentifier();
			String tripcode = post.getTripcode();
			String capcode = post.getCapcode();
			String email = post.getEmail();
			String subject = post.getSubject();
			String comment = post.getWorkComment();
			long timestamp = post.getTimestamp();
			boolean sage = post.isSage();
			boolean originalPoster = post.isOriginalPoster();
			boolean deleted = post.isDeleted();
			boolean useDefaultName = name.equals(defaultName) || name.isEmpty();
			int attachmentsCount = post.getAttachmentsCount();
			int iconsCount = post.getIconsCount();
			CharSequence charSequence = HtmlParser.parse(comment, markup, null, this);
			spanItems.clear();
			SpannableStringBuilder spannable = new SpannableStringBuilder(charSequence);
			replaceSpannable(spannable, '<', "&lt;");
			replaceSpannable(spannable, '>', "&gt;");
			Object[] spans = spannable.getSpans(0, spannable.length(), Object.class);
			for (Object span : spans)
			{
				getSpanType(span, decodeTo);
				int what = (int) decodeTo[0];
				if (what != 0)
				{
					int start = spannable.getSpanStart(span);
					int end = spannable.getSpanEnd(span);
					Object extra = decodeTo[1];
					if (what == ChanMarkup.TAG_SPECIAL_LINK)<commit_msg>Write default name if name is empty in local archiver<commit_after>/*
 * Copyright 2014-2016 <NAME>
 * 
 * Licensed 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 com.mishiranu.dashchan.async;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Locale;

import android.graphics.Typeface;
import android.net.Uri;
import android.text.SpannableStringBuilder;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.UnderlineSpan;

import chan.content.ChanConfiguration;
import chan.content.ChanLocator;
import chan.content.ChanMarkup;
import chan.content.model.Attachment;
import chan.content.model.FileAttachment;
import chan.content.model.Icon;
import chan.content.model.Post;
import chan.content.model.Posts;
import chan.util.StringUtils;

import com.mishiranu.dashchan.app.MainApplication;
import com.mishiranu.dashchan.app.service.DownloadService;
import com.mishiranu.dashchan.preference.Preferences;
import com.mishiranu.dashchan.text.HtmlParser;
import com.mishiranu.dashchan.text.WakabaLikeHtmlBuilder;
import com.mishiranu.dashchan.text.style.GainedColorSpan;
import com.mishiranu.dashchan.text.style.HeadingSpan;
import com.mishiranu.dashchan.text.style.LinkSpan;
import com.mishiranu.dashchan.text.style.MonospaceSpan;
import com.mishiranu.dashchan.text.style.OverlineSpan;
import com.mishiranu.dashchan.text.style.QuoteSpan;
import com.mishiranu.dashchan.text.style.ScriptSpan;
import com.mishiranu.dashchan.text.style.SpoilerSpan;
import com.mishiranu.dashchan.util.IOUtils;

public class SendLocalArchiveTask extends CancellableTask<Void, Integer, Object> implements ChanMarkup.MarkupExtra
{
	private final String mChanName;
	private final String mBoardName;
	private final String mThreadNumber;
	private final Posts mPosts;
	private final boolean mSaveThumbnails;
	private final boolean mSaveFiles;
	private final Callback mCallback;
	
	public static interface Callback
	{
		public void onLocalArchivationProgressUpdate(int handledPostsCount);
		public void onLocalArchivationComplete(boolean success, boolean showSuccess);
	}
	
	public SendLocalArchiveTask(String chanName, String boardName, String threadNumber,
			Posts posts, boolean saveThumbnails, boolean saveFiles, Callback callback)
	{
		mChanName = chanName;
		mBoardName = boardName;
		mThreadNumber = threadNumber;
		mPosts = posts;
		mSaveThumbnails = saveThumbnails;
		mSaveFiles = saveFiles;
		mCallback = callback;
	}
	
	@Override
	public String getBoardName()
	{
		return mBoardName;
	}
	
	@Override
	public String getThreadNumber()
	{
		return mThreadNumber;
	}
	
	private static class SpanItem
	{
		public int start;
		public int end;
		
		public final String openTag;
		public final String closeTag;
		
		public SpanItem(String openTag, String closeTag)
		{
			this.openTag = openTag;
			this.closeTag = closeTag;
		}
	}
	
	@Override
	protected Result doInBackground(Void... params)
	{
		String chanName = mChanName;
		String boardName = mBoardName;
		String threadNumber = mThreadNumber;
		Post[] posts = mPosts.getPosts();
		Object[] decodeTo = new Object[2];
		ArrayList<SpanItem> spanItems = new ArrayList<>();
		ChanConfiguration configuration = ChanConfiguration.get(mChanName);
		ChanLocator locator = ChanLocator.get(configuration);
		ChanMarkup markup = ChanMarkup.get(configuration);
		File directory = getLocalDownloadDirectory(true);
		String archiveDirectoryName = chanName + '-' + boardName + '-' + threadNumber;
		File filesDirectory = mSaveFiles ? new File(directory, archiveDirectoryName + "/src") : null;
		File thumbnailsDirectory = mSaveThumbnails ? new File(directory, archiveDirectoryName + "/thumb") : null;
		if (filesDirectory != null) filesDirectory.mkdirs();
		if (thumbnailsDirectory != null) thumbnailsDirectory.mkdirs();
		int totalFilesCount = 0;
		ArrayList<String> existFilesLc = new ArrayList<>();
		ArrayList<String> existThumbnailsLc = new ArrayList<>();
		for (Post post : posts) totalFilesCount += post.getAttachmentsCount();
		String defaultName = configuration.getDefaultName(boardName);
		WakabaLikeHtmlBuilder htmlBuilder = new WakabaLikeHtmlBuilder(posts[0].getSubject(), chanName, boardName,
				configuration .getBoardTitle(boardName), configuration.getTitle(),
				locator.safe(false).createThreadUri(boardName, threadNumber), posts.length, totalFilesCount);
		Result result = new Result(thumbnailsDirectory, filesDirectory);
		for (Post post : posts)
		{
			String number = post.getPostNumber();
			String name = StringUtils.emptyIfNull(post.getName()).trim();
			String identifier = post.getIdentifier();
			String tripcode = post.getTripcode();
			String capcode = post.getCapcode();
			String email = post.getEmail();
			String subject = post.getSubject();
			String comment = post.getWorkComment();
			long timestamp = post.getTimestamp();
			boolean sage = post.isSage();
			boolean originalPoster = post.isOriginalPoster();
			boolean deleted = post.isDeleted();
			boolean useDefaultName = name.equals(defaultName) || name.isEmpty();
			if (name.isEmpty()) name = defaultName;
			int attachmentsCount = post.getAttachmentsCount();
			int iconsCount = post.getIconsCount();
			CharSequence charSequence = HtmlParser.parse(comment, markup, null, this);
			spanItems.clear();
			SpannableStringBuilder spannable = new SpannableStringBuilder(charSequence);
			replaceSpannable(spannable, '<', "&lt;");
			replaceSpannable(spannable, '>', "&gt;");
			Object[] spans = spannable.getSpans(0, spannable.length(), Object.class);
			for (Object span : spans)
			{
				getSpanType(span, decodeTo);
				int what = (int) decodeTo[0];
				if (what != 0)
				{
					int start = spannable.getSpanStart(span);
					int end = spannable.getSpanEnd(span);
					Object extra = decodeTo[1];
					if (what == ChanMarkup.TAG_SPECIAL_LINK)
{'fraction_non_alphanumeric': 0.09898736164534108, 'fraction_numerical': 0.002982965695894497, 'mean_word_length': 5.116178588574172, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '675368', 'n_tokens_mistral': 4194, 'n_tokens_neox': 3762, 'n_words': 956}