public SortResult sort(File file, File temp, int threads, boolean verbose) throws InterruptedException, IOException {

        BufferedRandomAccessFile tempRaf = null;
        BufferedRandomAccessFile fileRaf = null;
        try {


            if ((temp = createIfAbsent(temp, verbose)) == null) {
                return SortResult.ERROR;
            }

            temp.deleteOnExit();

            int[][] blocks = new int[threads][];

            tempRaf = new BufferedRandomAccessFile(1024, temp, "rw");
            fileRaf = new BufferedRandomAccessFile(1024, file, "rw");


            int ints = (int) Math.min(file.length() / 4, 200000);

            for (int i = 0; i < threads; i++) {
                blocks[i] = new int[ints];
            }

            if (verbose) {
                System.out.printf("Sorting chunks of the base file, using %d threads.%n", threads);
            }

            boolean sortDone = sortChunks(blocks, fileRaf, tempRaf, threads);

            if (!sortDone) {
                System.err.println("Sorting process takes too long. Force termination.");
                return SortResult.ERROR;
            }

            if (verbose) {
                System.out.println("Sorting round finished");
            }


            long chunkSize = ints * 4;

            tempRaf.seek(0);
            fileRaf.seek(0);


            BufferedRandomAccessFile input = tempRaf;
            BufferedRandomAccessFile output = fileRaf;
            DataOutputStream outputStream = Utils.getBufferedStream(output);

            int round = 0;

            while (chunkSize < input.length()) {

                if (verbose) {
                    System.out.printf("Merging chunks of %d numbers%n", chunkSize / 4);
                }

                long offset = 0;
                long usedChunks;
                long maxUsedChunks = 2;

                while (offset < input.length()) {
                    usedChunks = merge(input, outputStream, offset, chunkSize, blocks);
                    offset = offset + chunkSize * usedChunks;
                    maxUsedChunks = Math.max(maxUsedChunks, usedChunks);
                }

                chunkSize *= maxUsedChunks;
                input.seek(0);
                output.seek(0);

                BufferedRandomAccessFile t = input;
                input = output;
                output = t;

                outputStream.flush();
                outputStream = Utils.getBufferedStream(output);

                round++;

            }

            if (round % 2 == 0) {
                Files.copy(temp.toPath(), file.toPath(), REPLACE_EXISTING);
            }

            return SortResult.WELL_DONE;

        } finally {
            Utils.closeQuietly(fileRaf);
            Utils.closeQuietly(tempRaf);
        }

    }